148 code[DifferenceCompositionModeFragmentShader] = ""; //### |
149 code[DifferenceCompositionModeFragmentShader] = ""; //### |
149 code[ExclusionCompositionModeFragmentShader] = ""; //### |
150 code[ExclusionCompositionModeFragmentShader] = ""; //### |
150 |
151 |
151 #if defined(QT_DEBUG) |
152 #if defined(QT_DEBUG) |
152 // Check that all the elements have been filled: |
153 // Check that all the elements have been filled: |
153 for (int i = 0; i < TotalShaderCount; ++i) { |
154 for (int i = 0; i < TotalSnippetCount; ++i) { |
154 if (qglEngineShaderSourceCode[i] == 0) { |
155 if (qShaderSnippets[i] == 0) { |
155 int enumIndex = staticMetaObject.indexOfEnumerator("ShaderName"); |
156 qFatal("Shader snippet for %s (#%d) is missing!", |
156 QMetaEnum m = staticMetaObject.enumerator(enumIndex); |
157 snippetNameStr(SnippetName(i)).constData(), i); |
157 |
|
158 qCritical() << "qglEngineShaderSourceCode: Source for" << m.valueToKey(i) |
|
159 << "(shader" << i << ") missing!"; |
|
160 } |
158 } |
161 } |
159 } |
162 #endif |
160 #endif |
163 qglEngineShaderSourceCodePopulated = true; |
161 snippetsPopulated = true; |
164 } |
162 } |
|
163 |
|
164 QGLShader* fragShader; |
|
165 QGLShader* vertexShader; |
|
166 QByteArray source; |
165 |
167 |
166 // Compile up the simple shader: |
168 // Compile up the simple shader: |
|
169 source.clear(); |
|
170 source.append(qShaderSnippets[MainVertexShader]); |
|
171 source.append(qShaderSnippets[PositionOnlyVertexShader]); |
|
172 vertexShader = new QGLShader(QGLShader::Vertex, context, this); |
|
173 vertexShader->compileSourceCode(source); |
|
174 |
|
175 source.clear(); |
|
176 source.append(qShaderSnippets[MainFragmentShader]); |
|
177 source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); |
|
178 fragShader = new QGLShader(QGLShader::Fragment, context, this); |
|
179 fragShader->compileSourceCode(source); |
|
180 |
167 simpleShaderProg = new QGLShaderProgram(context, this); |
181 simpleShaderProg = new QGLShaderProgram(context, this); |
168 compileNamedShader(MainVertexShader, QGLShader::PartialVertexShader); |
182 simpleShaderProg->addShader(vertexShader); |
169 compileNamedShader(PositionOnlyVertexShader, QGLShader::PartialVertexShader); |
183 simpleShaderProg->addShader(fragShader); |
170 compileNamedShader(MainFragmentShader, QGLShader::PartialFragmentShader); |
|
171 compileNamedShader(ShockingPinkSrcFragmentShader, QGLShader::PartialFragmentShader); |
|
172 simpleShaderProg->addShader(compiledShaders[MainVertexShader]); |
|
173 simpleShaderProg->addShader(compiledShaders[PositionOnlyVertexShader]); |
|
174 simpleShaderProg->addShader(compiledShaders[MainFragmentShader]); |
|
175 simpleShaderProg->addShader(compiledShaders[ShockingPinkSrcFragmentShader]); |
|
176 simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); |
184 simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); |
177 simpleShaderProg->link(); |
185 simpleShaderProg->link(); |
178 if (!simpleShaderProg->isLinked()) { |
186 if (!simpleShaderProg->isLinked()) { |
179 qCritical() << "Errors linking simple shader:" |
187 qCritical() << "Errors linking simple shader:" |
180 << simpleShaderProg->log(); |
188 << simpleShaderProg->log(); |
181 } |
189 } |
182 |
190 |
183 // Compile the blit shader: |
191 // Compile the blit shader: |
|
192 source.clear(); |
|
193 source.append(qShaderSnippets[MainWithTexCoordsVertexShader]); |
|
194 source.append(qShaderSnippets[UntransformedPositionVertexShader]); |
|
195 vertexShader = new QGLShader(QGLShader::Vertex, context, this); |
|
196 vertexShader->compileSourceCode(source); |
|
197 |
|
198 source.clear(); |
|
199 source.append(qShaderSnippets[MainFragmentShader]); |
|
200 source.append(qShaderSnippets[ImageSrcFragmentShader]); |
|
201 fragShader = new QGLShader(QGLShader::Fragment, context, this); |
|
202 fragShader->compileSourceCode(source); |
|
203 |
184 blitShaderProg = new QGLShaderProgram(context, this); |
204 blitShaderProg = new QGLShaderProgram(context, this); |
185 compileNamedShader(MainWithTexCoordsVertexShader, QGLShader::PartialVertexShader); |
205 blitShaderProg->addShader(vertexShader); |
186 compileNamedShader(UntransformedPositionVertexShader, QGLShader::PartialVertexShader); |
206 blitShaderProg->addShader(fragShader); |
187 compileNamedShader(MainFragmentShader, QGLShader::PartialFragmentShader); |
|
188 compileNamedShader(ImageSrcFragmentShader, QGLShader::PartialFragmentShader); |
|
189 blitShaderProg->addShader(compiledShaders[MainWithTexCoordsVertexShader]); |
|
190 blitShaderProg->addShader(compiledShaders[UntransformedPositionVertexShader]); |
|
191 blitShaderProg->addShader(compiledShaders[MainFragmentShader]); |
|
192 blitShaderProg->addShader(compiledShaders[ImageSrcFragmentShader]); |
|
193 blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); |
207 blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); |
194 blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); |
208 blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); |
195 blitShaderProg->link(); |
209 blitShaderProg->link(); |
196 if (!blitShaderProg->isLinked()) { |
210 if (!blitShaderProg->isLinked()) { |
197 qCritical() << "Errors linking blit shader:" |
211 qCritical() << "Errors linking blit shader:" |
198 << blitShaderProg->log(); |
212 << simpleShaderProg->log(); |
199 } |
213 } |
200 } |
214 |
201 |
215 } |
202 void QGLEngineSharedShaders::shaderDestroyed(QObject *shader) |
216 |
203 { |
217 #if defined (QT_DEBUG) |
204 // Remove any shader programs which has this as the srcPixel shader: |
218 QByteArray QGLEngineSharedShaders::snippetNameStr(SnippetName name) |
205 for (int i = 0; i < cachedPrograms.size(); ++i) { |
219 { |
206 if (cachedPrograms.at(i).srcPixelFragShader == shader) { |
220 QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName")); |
207 delete cachedPrograms.at(i).program; |
221 return QByteArray(m.valueToKey(name)); |
208 cachedPrograms.removeAt(i--); |
222 } |
209 } |
|
210 } |
|
211 |
|
212 emit shaderProgNeedsChanging(); |
|
213 } |
|
214 |
|
215 QGLShader *QGLEngineSharedShaders::compileNamedShader(ShaderName name, QGLShader::ShaderType type) |
|
216 { |
|
217 Q_ASSERT(name != CustomImageSrcFragmentShader); |
|
218 Q_ASSERT(name < InvalidShaderName); |
|
219 |
|
220 if (compiledShaders[name]) |
|
221 return compiledShaders[name]; |
|
222 |
|
223 QByteArray source = qglEngineShaderSourceCode[name]; |
|
224 QGLShader *newShader = new QGLShader(type, ctxGuard.context(), this); |
|
225 newShader->compile(source); |
|
226 |
|
227 #if defined(QT_DEBUG) |
|
228 // Name the shader for easier debugging |
|
229 QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("ShaderName")); |
|
230 newShader->setObjectName(QLatin1String(m.valueToKey(name))); |
|
231 #endif |
223 #endif |
232 |
|
233 compiledShaders[name] = newShader; |
|
234 return newShader; |
|
235 } |
|
236 |
|
237 QGLShader *QGLEngineSharedShaders::compileCustomShader(QGLCustomShaderStage *stage, QGLShader::ShaderType type) |
|
238 { |
|
239 QByteArray source = stage->source(); |
|
240 source += qglslCustomSrcFragmentShader; |
|
241 |
|
242 QGLShader *newShader = customShaderCache.object(source); |
|
243 if (newShader) |
|
244 return newShader; |
|
245 |
|
246 newShader = new QGLShader(type, ctxGuard.context(), this); |
|
247 newShader->compile(source); |
|
248 customShaderCache.insert(source, newShader); |
|
249 |
|
250 connect(newShader, SIGNAL(destroyed(QObject *)), |
|
251 this, SLOT(shaderDestroyed(QObject *))); |
|
252 |
|
253 #if defined(QT_DEBUG) |
|
254 // Name the shader for easier debugging |
|
255 QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("ShaderName")); |
|
256 newShader->setObjectName(QLatin1String(m.valueToKey(CustomImageSrcFragmentShader))); |
|
257 #endif |
|
258 |
|
259 return newShader; |
|
260 } |
|
261 |
224 |
262 // The address returned here will only be valid until next time this function is called. |
225 // The address returned here will only be valid until next time this function is called. |
263 QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog) |
226 QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog) |
264 { |
227 { |
265 for (int i = 0; i < cachedPrograms.size(); ++i) { |
228 for (int i = 0; i < cachedPrograms.size(); ++i) { |
266 if (cachedPrograms[i] == prog) |
229 QGLEngineShaderProg *cachedProg = cachedPrograms[i]; |
267 return &cachedPrograms[i]; |
230 if (*cachedProg == prog) { |
268 } |
231 // Move the program to the top of the list as a poor-man's cache algo |
269 |
232 cachedPrograms.move(i, 0); |
270 cachedPrograms.append(prog); |
233 return cachedProg; |
271 QGLEngineShaderProg &cached = cachedPrograms.last(); |
234 } |
|
235 } |
|
236 |
|
237 QByteArray source; |
|
238 source.append(qShaderSnippets[prog.mainFragShader]); |
|
239 source.append(qShaderSnippets[prog.srcPixelFragShader]); |
|
240 if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) |
|
241 source.append(prog.customStageSource); |
|
242 if (prog.compositionFragShader) |
|
243 source.append(qShaderSnippets[prog.compositionFragShader]); |
|
244 if (prog.maskFragShader) |
|
245 source.append(qShaderSnippets[prog.maskFragShader]); |
|
246 QGLShader* fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); |
|
247 fragShader->compileSourceCode(source); |
|
248 |
|
249 source.clear(); |
|
250 source.append(qShaderSnippets[prog.mainVertexShader]); |
|
251 source.append(qShaderSnippets[prog.positionVertexShader]); |
|
252 QGLShader* vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); |
|
253 vertexShader->compileSourceCode(source); |
|
254 |
|
255 #if defined(QT_DEBUG) |
|
256 // Name the shaders for easier debugging |
|
257 QByteArray description; |
|
258 description.append("Fragment shader: main="); |
|
259 description.append(snippetNameStr(prog.mainFragShader)); |
|
260 description.append(", srcPixel="); |
|
261 description.append(snippetNameStr(prog.srcPixelFragShader)); |
|
262 if (prog.compositionFragShader) { |
|
263 description.append(", composition="); |
|
264 description.append(snippetNameStr(prog.compositionFragShader)); |
|
265 } |
|
266 if (prog.maskFragShader) { |
|
267 description.append(", mask="); |
|
268 description.append(snippetNameStr(prog.maskFragShader)); |
|
269 } |
|
270 fragShader->setObjectName(QString::fromLatin1(description)); |
|
271 |
|
272 description.clear(); |
|
273 description.append("Vertex shader: main="); |
|
274 description.append(snippetNameStr(prog.mainVertexShader)); |
|
275 description.append(", position="); |
|
276 description.append(snippetNameStr(prog.positionVertexShader)); |
|
277 vertexShader->setObjectName(QString::fromLatin1(description)); |
|
278 #endif |
|
279 |
|
280 QGLEngineShaderProg* newProg = new QGLEngineShaderProg(prog); |
272 |
281 |
273 // If the shader program's not found in the cache, create it now. |
282 // If the shader program's not found in the cache, create it now. |
274 cached.program = new QGLShaderProgram(ctxGuard.context(), this); |
283 newProg->program = new QGLShaderProgram(ctxGuard.context(), this); |
275 cached.program->addShader(cached.mainVertexShader); |
284 newProg->program->addShader(vertexShader); |
276 cached.program->addShader(cached.positionVertexShader); |
285 newProg->program->addShader(fragShader); |
277 cached.program->addShader(cached.mainFragShader); |
|
278 cached.program->addShader(cached.srcPixelFragShader); |
|
279 cached.program->addShader(cached.maskFragShader); |
|
280 cached.program->addShader(cached.compositionFragShader); |
|
281 |
286 |
282 // We have to bind the vertex attribute names before the program is linked: |
287 // We have to bind the vertex attribute names before the program is linked: |
283 cached.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); |
288 newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); |
284 if (cached.useTextureCoords) |
289 if (newProg->useTextureCoords) |
285 cached.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); |
290 newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); |
286 if (cached.useOpacityAttribute) |
291 if (newProg->useOpacityAttribute) |
287 cached.program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); |
292 newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); |
288 |
293 |
289 cached.program->link(); |
294 newProg->program->link(); |
290 if (!cached.program->isLinked()) { |
295 if (!newProg->program->isLinked()) { |
291 QLatin1String none("none"); |
296 QLatin1String none("none"); |
292 QLatin1String br("\n"); |
297 QLatin1String br("\n"); |
293 QString error; |
298 QString error; |
294 error = QLatin1String("Shader program failed to link,") |
299 error = QLatin1String("Shader program failed to link,") |
295 #if defined(QT_DEBUG) |
300 #if defined(QT_DEBUG) |
296 + br |
301 + br |
297 + QLatin1String(" Shaders Used:\n") |
302 + QLatin1String(" Shaders Used:") + br |
298 + QLatin1String(" mainVertexShader = ") |
303 + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br |
299 + (cached.mainVertexShader ? |
304 + QLatin1String(vertexShader->sourceCode()) + br |
300 cached.mainVertexShader->objectName() : none) + br |
305 + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br |
301 + QLatin1String(" positionVertexShader = ") |
306 + QLatin1String(fragShader->sourceCode()) + br |
302 + (cached.positionVertexShader ? |
|
303 cached.positionVertexShader->objectName() : none) + br |
|
304 + QLatin1String(" mainFragShader = ") |
|
305 + (cached.mainFragShader ? |
|
306 cached.mainFragShader->objectName() : none) + br |
|
307 + QLatin1String(" srcPixelFragShader = ") |
|
308 + (cached.srcPixelFragShader ? |
|
309 cached.srcPixelFragShader->objectName() : none) + br |
|
310 + QLatin1String(" maskFragShader = ") |
|
311 + (cached.maskFragShader ? |
|
312 cached.maskFragShader->objectName() : none) + br |
|
313 + QLatin1String(" compositionFragShader = ") |
|
314 + (cached.compositionFragShader ? |
|
315 cached.compositionFragShader->objectName() : none) + br |
|
316 #endif |
307 #endif |
317 + QLatin1String(" Error Log:\n") |
308 + QLatin1String(" Error Log:\n") |
318 + QLatin1String(" ") + cached.program->log(); |
309 + QLatin1String(" ") + newProg->program->log(); |
319 qWarning() << error; |
310 qWarning() << error; |
320 delete cached.program; |
311 delete newProg; // Deletes the QGLShaderProgram in it's destructor |
321 cachedPrograms.removeLast(); |
312 newProg = 0; |
322 return 0; |
313 } |
323 } else { |
314 else { |
324 // taking the address here is safe since |
315 if (cachedPrograms.count() > 30) { |
325 // cachePrograms isn't resized anywhere else |
316 // The cache is full, so delete the last 5 programs in the list. |
326 return &cached; |
317 // These programs will be least used, as a program us bumped to |
327 } |
318 // the top of the list when it's used. |
328 } |
319 for (int i = 0; i < 5; ++i) { |
|
320 delete cachedPrograms.last(); |
|
321 cachedPrograms.removeLast(); |
|
322 } |
|
323 } |
|
324 |
|
325 cachedPrograms.insert(0, newProg); |
|
326 } |
|
327 |
|
328 return newProg; |
|
329 } |
|
330 |
|
331 void QGLEngineSharedShaders::cleanupCustomStage(QGLCustomShaderStage* stage) |
|
332 { |
|
333 // Remove any shader programs which has this as the custom shader src: |
|
334 for (int i = 0; i < cachedPrograms.size(); ++i) { |
|
335 QGLEngineShaderProg *cachedProg = cachedPrograms[i]; |
|
336 if (cachedProg->customStageSource == stage->source()) { |
|
337 delete cachedProg; |
|
338 cachedPrograms.removeAt(i); |
|
339 i--; |
|
340 } |
|
341 } |
|
342 } |
|
343 |
329 |
344 |
330 QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) |
345 QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) |
331 : ctx(context), |
346 : ctx(context), |
332 shaderProgNeedsChanging(true), |
347 shaderProgNeedsChanging(true), |
333 srcPixelType(Qt::NoBrush), |
348 srcPixelType(Qt::NoBrush), |
334 opacityMode(NoOpacity), |
349 opacityMode(NoOpacity), |
335 maskType(NoMask), |
350 maskType(NoMask), |
336 compositionMode(QPainter::CompositionMode_SourceOver), |
351 compositionMode(QPainter::CompositionMode_SourceOver), |
337 customSrcStage(0), |
352 customSrcStage(0), |
338 currentShaderProg(0), |
353 currentShaderProg(0) |
339 customShader(0) |
|
340 { |
354 { |
341 sharedShaders = QGLEngineSharedShaders::shadersForContext(context); |
355 sharedShaders = QGLEngineSharedShaders::shadersForContext(context); |
342 connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot())); |
356 connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot())); |
343 } |
357 } |
344 |
358 |
345 QGLEngineShaderManager::~QGLEngineShaderManager() |
359 QGLEngineShaderManager::~QGLEngineShaderManager() |
346 { |
360 { |
347 //### |
361 //### |
|
362 removeCustomStage(); |
348 } |
363 } |
349 |
364 |
350 uint QGLEngineShaderManager::getUniformLocation(Uniform id) |
365 uint QGLEngineShaderManager::getUniformLocation(Uniform id) |
351 { |
366 { |
352 QVector<uint> &uniformLocations = currentShaderProg->uniformLocations; |
367 QVector<uint> &uniformLocations = currentShaderProg->uniformLocations; |
474 { |
489 { |
475 if (!shaderProgNeedsChanging) |
490 if (!shaderProgNeedsChanging) |
476 return false; |
491 return false; |
477 |
492 |
478 bool useCustomSrc = customSrcStage != 0; |
493 bool useCustomSrc = customSrcStage != 0; |
479 if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc) { |
494 if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) { |
480 useCustomSrc = false; |
495 useCustomSrc = false; |
481 qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src"); |
496 qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src"); |
482 } |
497 } |
483 |
498 |
484 QGLEngineShaderProg requiredProgram; |
499 QGLEngineShaderProg requiredProgram; |
485 requiredProgram.program = 0; |
|
486 |
500 |
487 bool texCoords = false; |
501 bool texCoords = false; |
488 |
502 |
489 // Choose vertex shader shader position function (which typically also sets |
503 // Choose vertex shader shader position function (which typically also sets |
490 // varyings) and the source pixel (srcPixel) fragment shader function: |
504 // varyings) and the source pixel (srcPixel) fragment shader function: |
491 QGLEngineSharedShaders::ShaderName positionVertexShaderName = QGLEngineSharedShaders::InvalidShaderName; |
505 requiredProgram.positionVertexShader = QGLEngineSharedShaders::InvalidSnippetName; |
492 QGLEngineSharedShaders::ShaderName srcPixelFragShaderName = QGLEngineSharedShaders::InvalidShaderName; |
506 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::InvalidSnippetName; |
493 bool isAffine = brushTransform.isAffine(); |
507 bool isAffine = brushTransform.isAffine(); |
494 if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) { |
508 if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) { |
495 if (isAffine) |
509 if (isAffine) |
496 positionVertexShaderName = QGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader; |
510 requiredProgram.positionVertexShader = QGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader; |
497 else |
511 else |
498 positionVertexShaderName = QGLEngineSharedShaders::PositionWithPatternBrushVertexShader; |
512 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionWithPatternBrushVertexShader; |
499 |
513 |
500 srcPixelFragShaderName = QGLEngineSharedShaders::PatternBrushSrcFragmentShader; |
514 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::PatternBrushSrcFragmentShader; |
501 } |
515 } |
502 else switch (srcPixelType) { |
516 else switch (srcPixelType) { |
503 default: |
517 default: |
504 case Qt::NoBrush: |
518 case Qt::NoBrush: |
505 qFatal("QGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set"); |
519 qFatal("QGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set"); |
506 break; |
520 break; |
507 case QGLEngineShaderManager::ImageSrc: |
521 case QGLEngineShaderManager::ImageSrc: |
508 srcPixelFragShaderName = QGLEngineSharedShaders::ImageSrcFragmentShader; |
522 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcFragmentShader; |
509 positionVertexShaderName = QGLEngineSharedShaders::PositionOnlyVertexShader; |
523 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader; |
510 texCoords = true; |
524 texCoords = true; |
511 break; |
525 break; |
512 case QGLEngineShaderManager::NonPremultipliedImageSrc: |
526 case QGLEngineShaderManager::NonPremultipliedImageSrc: |
513 srcPixelFragShaderName = QGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader; |
527 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader; |
514 positionVertexShaderName = QGLEngineSharedShaders::PositionOnlyVertexShader; |
528 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader; |
515 texCoords = true; |
529 texCoords = true; |
516 break; |
530 break; |
517 case QGLEngineShaderManager::PatternSrc: |
531 case QGLEngineShaderManager::PatternSrc: |
518 srcPixelFragShaderName = QGLEngineSharedShaders::ImageSrcWithPatternFragmentShader; |
532 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcWithPatternFragmentShader; |
519 positionVertexShaderName = QGLEngineSharedShaders::PositionOnlyVertexShader; |
533 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader; |
520 texCoords = true; |
534 texCoords = true; |
521 break; |
535 break; |
522 case QGLEngineShaderManager::TextureSrcWithPattern: |
536 case QGLEngineShaderManager::TextureSrcWithPattern: |
523 srcPixelFragShaderName = QGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader; |
537 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader; |
524 positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader |
538 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader |
525 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader; |
539 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader; |
526 break; |
540 break; |
527 case Qt::SolidPattern: |
541 case Qt::SolidPattern: |
528 srcPixelFragShaderName = QGLEngineSharedShaders::SolidBrushSrcFragmentShader; |
542 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::SolidBrushSrcFragmentShader; |
529 positionVertexShaderName = QGLEngineSharedShaders::PositionOnlyVertexShader; |
543 requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader; |
530 break; |
544 break; |
531 case Qt::LinearGradientPattern: |
545 case Qt::LinearGradientPattern: |
532 srcPixelFragShaderName = QGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader; |
546 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader; |
533 positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader |
547 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader |
534 : QGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader; |
548 : QGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader; |
535 break; |
549 break; |
536 case Qt::ConicalGradientPattern: |
550 case Qt::ConicalGradientPattern: |
537 srcPixelFragShaderName = QGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader; |
551 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader; |
538 positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader |
552 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader |
539 : QGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader; |
553 : QGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader; |
540 break; |
554 break; |
541 case Qt::RadialGradientPattern: |
555 case Qt::RadialGradientPattern: |
542 srcPixelFragShaderName = QGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader; |
556 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader; |
543 positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader |
557 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader |
544 : QGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader; |
558 : QGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader; |
545 break; |
559 break; |
546 case Qt::TexturePattern: |
560 case Qt::TexturePattern: |
547 srcPixelFragShaderName = QGLEngineSharedShaders::TextureBrushSrcFragmentShader; |
561 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcFragmentShader; |
548 positionVertexShaderName = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader |
562 requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader |
549 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader; |
563 : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader; |
550 break; |
564 break; |
551 }; |
565 }; |
552 requiredProgram.positionVertexShader = sharedShaders->compileNamedShader(positionVertexShaderName, QGLShader::PartialVertexShader); |
566 |
553 if (useCustomSrc) { |
567 if (useCustomSrc) { |
554 if (!customShader) |
568 requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::CustomImageSrcFragmentShader; |
555 customShader = sharedShaders->compileCustomShader(customSrcStage, QGLShader::PartialFragmentShader); |
569 requiredProgram.customStageSource = customSrcStage->source(); |
556 requiredProgram.srcPixelFragShader = customShader; |
|
557 } else { |
|
558 requiredProgram.srcPixelFragShader = sharedShaders->compileNamedShader(srcPixelFragShaderName, QGLShader::PartialFragmentShader); |
|
559 } |
570 } |
560 |
571 |
561 const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus; |
572 const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus; |
562 const bool hasMask = maskType != QGLEngineShaderManager::NoMask; |
573 const bool hasMask = maskType != QGLEngineShaderManager::NoMask; |
563 |
574 |
564 // Choose fragment shader main function: |
575 // Choose fragment shader main function: |
565 QGLEngineSharedShaders::ShaderName mainFragShaderName; |
|
566 |
|
567 if (opacityMode == AttributeOpacity) { |
576 if (opacityMode == AttributeOpacity) { |
568 Q_ASSERT(!hasCompose && !hasMask); |
577 Q_ASSERT(!hasCompose && !hasMask); |
569 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_ImageArrays; |
578 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_ImageArrays; |
570 } else { |
579 } else { |
571 bool useGlobalOpacity = (opacityMode == UniformOpacity); |
580 bool useGlobalOpacity = (opacityMode == UniformOpacity); |
572 if (hasCompose && hasMask && useGlobalOpacity) |
581 if (hasCompose && hasMask && useGlobalOpacity) |
573 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CMO; |
582 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CMO; |
574 if (hasCompose && hasMask && !useGlobalOpacity) |
583 if (hasCompose && hasMask && !useGlobalOpacity) |
575 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CM; |
584 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CM; |
576 if (!hasCompose && hasMask && useGlobalOpacity) |
585 if (!hasCompose && hasMask && useGlobalOpacity) |
577 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_MO; |
586 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_MO; |
578 if (!hasCompose && hasMask && !useGlobalOpacity) |
587 if (!hasCompose && hasMask && !useGlobalOpacity) |
579 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_M; |
588 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_M; |
580 if (hasCompose && !hasMask && useGlobalOpacity) |
589 if (hasCompose && !hasMask && useGlobalOpacity) |
581 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_CO; |
590 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CO; |
582 if (hasCompose && !hasMask && !useGlobalOpacity) |
591 if (hasCompose && !hasMask && !useGlobalOpacity) |
583 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_C; |
592 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_C; |
584 if (!hasCompose && !hasMask && useGlobalOpacity) |
593 if (!hasCompose && !hasMask && useGlobalOpacity) |
585 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader_O; |
594 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_O; |
586 if (!hasCompose && !hasMask && !useGlobalOpacity) |
595 if (!hasCompose && !hasMask && !useGlobalOpacity) |
587 mainFragShaderName = QGLEngineSharedShaders::MainFragmentShader; |
596 requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader; |
588 } |
597 } |
589 |
|
590 requiredProgram.mainFragShader = sharedShaders->compileNamedShader(mainFragShaderName, QGLShader::PartialFragmentShader); |
|
591 |
598 |
592 if (hasMask) { |
599 if (hasMask) { |
593 QGLEngineSharedShaders::ShaderName maskShaderName = QGLEngineSharedShaders::InvalidShaderName; |
|
594 if (maskType == PixelMask) { |
600 if (maskType == PixelMask) { |
595 maskShaderName = QGLEngineSharedShaders::MaskFragmentShader; |
601 requiredProgram.maskFragShader = QGLEngineSharedShaders::MaskFragmentShader; |
596 texCoords = true; |
602 texCoords = true; |
597 } else if (maskType == SubPixelMaskPass1) { |
603 } else if (maskType == SubPixelMaskPass1) { |
598 maskShaderName = QGLEngineSharedShaders::RgbMaskFragmentShaderPass1; |
604 requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass1; |
599 texCoords = true; |
605 texCoords = true; |
600 } else if (maskType == SubPixelMaskPass2) { |
606 } else if (maskType == SubPixelMaskPass2) { |
601 maskShaderName = QGLEngineSharedShaders::RgbMaskFragmentShaderPass2; |
607 requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass2; |
602 texCoords = true; |
608 texCoords = true; |
603 } else if (maskType == SubPixelWithGammaMask) { |
609 } else if (maskType == SubPixelWithGammaMask) { |
604 maskShaderName = QGLEngineSharedShaders::RgbMaskWithGammaFragmentShader; |
610 requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskWithGammaFragmentShader; |
605 texCoords = true; |
611 texCoords = true; |
606 } else { |
612 } else { |
607 qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type"); |
613 qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type"); |
608 } |
614 } |
609 |
|
610 requiredProgram.maskFragShader = sharedShaders->compileNamedShader(maskShaderName, QGLShader::PartialFragmentShader); |
|
611 } else { |
615 } else { |
612 requiredProgram.maskFragShader = 0; |
616 requiredProgram.maskFragShader = QGLEngineSharedShaders::NoMaskFragmentShader; |
613 } |
617 } |
614 |
618 |
615 if (hasCompose) { |
619 if (hasCompose) { |
616 QGLEngineSharedShaders::ShaderName compositionShaderName = QGLEngineSharedShaders::InvalidShaderName; |
|
617 switch (compositionMode) { |
620 switch (compositionMode) { |
618 case QPainter::CompositionMode_Multiply: |
621 case QPainter::CompositionMode_Multiply: |
619 compositionShaderName = QGLEngineSharedShaders::MultiplyCompositionModeFragmentShader; |
622 requiredProgram.compositionFragShader = QGLEngineSharedShaders::MultiplyCompositionModeFragmentShader; |
620 break; |
623 break; |
621 case QPainter::CompositionMode_Screen: |
624 case QPainter::CompositionMode_Screen: |
622 compositionShaderName = QGLEngineSharedShaders::ScreenCompositionModeFragmentShader; |
625 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ScreenCompositionModeFragmentShader; |
623 break; |
626 break; |
624 case QPainter::CompositionMode_Overlay: |
627 case QPainter::CompositionMode_Overlay: |
625 compositionShaderName = QGLEngineSharedShaders::OverlayCompositionModeFragmentShader; |
628 requiredProgram.compositionFragShader = QGLEngineSharedShaders::OverlayCompositionModeFragmentShader; |
626 break; |
629 break; |
627 case QPainter::CompositionMode_Darken: |
630 case QPainter::CompositionMode_Darken: |
628 compositionShaderName = QGLEngineSharedShaders::DarkenCompositionModeFragmentShader; |
631 requiredProgram.compositionFragShader = QGLEngineSharedShaders::DarkenCompositionModeFragmentShader; |
629 break; |
632 break; |
630 case QPainter::CompositionMode_Lighten: |
633 case QPainter::CompositionMode_Lighten: |
631 compositionShaderName = QGLEngineSharedShaders::LightenCompositionModeFragmentShader; |
634 requiredProgram.compositionFragShader = QGLEngineSharedShaders::LightenCompositionModeFragmentShader; |
632 break; |
635 break; |
633 case QPainter::CompositionMode_ColorDodge: |
636 case QPainter::CompositionMode_ColorDodge: |
634 compositionShaderName = QGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader; |
637 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader; |
635 break; |
638 break; |
636 case QPainter::CompositionMode_ColorBurn: |
639 case QPainter::CompositionMode_ColorBurn: |
637 compositionShaderName = QGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader; |
640 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader; |
638 break; |
641 break; |
639 case QPainter::CompositionMode_HardLight: |
642 case QPainter::CompositionMode_HardLight: |
640 compositionShaderName = QGLEngineSharedShaders::HardLightCompositionModeFragmentShader; |
643 requiredProgram.compositionFragShader = QGLEngineSharedShaders::HardLightCompositionModeFragmentShader; |
641 break; |
644 break; |
642 case QPainter::CompositionMode_SoftLight: |
645 case QPainter::CompositionMode_SoftLight: |
643 compositionShaderName = QGLEngineSharedShaders::SoftLightCompositionModeFragmentShader; |
646 requiredProgram.compositionFragShader = QGLEngineSharedShaders::SoftLightCompositionModeFragmentShader; |
644 break; |
647 break; |
645 case QPainter::CompositionMode_Difference: |
648 case QPainter::CompositionMode_Difference: |
646 compositionShaderName = QGLEngineSharedShaders::DifferenceCompositionModeFragmentShader; |
649 requiredProgram.compositionFragShader = QGLEngineSharedShaders::DifferenceCompositionModeFragmentShader; |
647 break; |
650 break; |
648 case QPainter::CompositionMode_Exclusion: |
651 case QPainter::CompositionMode_Exclusion: |
649 compositionShaderName = QGLEngineSharedShaders::ExclusionCompositionModeFragmentShader; |
652 requiredProgram.compositionFragShader = QGLEngineSharedShaders::ExclusionCompositionModeFragmentShader; |
650 break; |
653 break; |
651 default: |
654 default: |
652 qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode"); |
655 qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode"); |
653 } |
656 } |
654 requiredProgram.compositionFragShader = sharedShaders->compileNamedShader(compositionShaderName, QGLShader::PartialFragmentShader); |
|
655 } else { |
657 } else { |
656 requiredProgram.compositionFragShader = 0; |
658 requiredProgram.compositionFragShader = QGLEngineSharedShaders::NoCompositionModeFragmentShader; |
657 } |
659 } |
658 |
660 |
659 // Choose vertex shader main function |
661 // Choose vertex shader main function |
660 QGLEngineSharedShaders::ShaderName mainVertexShaderName = QGLEngineSharedShaders::InvalidShaderName; |
|
661 if (opacityMode == AttributeOpacity) { |
662 if (opacityMode == AttributeOpacity) { |
662 Q_ASSERT(texCoords); |
663 Q_ASSERT(texCoords); |
663 mainVertexShaderName = QGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader; |
664 requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader; |
664 } else if (texCoords) { |
665 } else if (texCoords) { |
665 mainVertexShaderName = QGLEngineSharedShaders::MainWithTexCoordsVertexShader; |
666 requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsVertexShader; |
666 } else { |
667 } else { |
667 mainVertexShaderName = QGLEngineSharedShaders::MainVertexShader; |
668 requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainVertexShader; |
668 } |
669 } |
669 requiredProgram.mainVertexShader = sharedShaders->compileNamedShader(mainVertexShaderName, QGLShader::PartialVertexShader); |
|
670 requiredProgram.useTextureCoords = texCoords; |
670 requiredProgram.useTextureCoords = texCoords; |
671 requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity); |
671 requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity); |
672 |
672 |
673 |
|
674 // At this point, requiredProgram is fully populated so try to find the program in the cache |
673 // At this point, requiredProgram is fully populated so try to find the program in the cache |
675 currentShaderProg = sharedShaders->findProgramInCache(requiredProgram); |
674 currentShaderProg = sharedShaders->findProgramInCache(requiredProgram); |
676 |
675 |
677 if (currentShaderProg) { |
676 if (currentShaderProg) { |
678 currentShaderProg->program->enable(); |
677 currentShaderProg->program->bind(); |
679 if (useCustomSrc) |
678 if (useCustomSrc) |
680 customSrcStage->setUniforms(currentShaderProg->program); |
679 customSrcStage->setUniforms(currentShaderProg->program); |
681 } |
680 } |
682 |
681 |
683 shaderProgNeedsChanging = false; |
682 shaderProgNeedsChanging = false; |