1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include "Context.hpp" |
16 | |
17 | #include "Primitive.hpp" |
18 | #include "Surface.hpp" |
19 | #include "Shader/PixelShader.hpp" |
20 | #include "Shader/VertexShader.hpp" |
21 | #include "Common/Memory.hpp" |
22 | #include "Common/Debug.hpp" |
23 | |
24 | #include <string.h> |
25 | |
26 | namespace sw |
27 | { |
28 | extern bool perspectiveCorrection; |
29 | |
30 | bool halfIntegerCoordinates = false; // Pixel centers are not at integer coordinates |
31 | bool symmetricNormalizedDepth = false; // [-1, 1] instead of [0, 1] |
32 | bool booleanFaceRegister = false; |
33 | bool fullPixelPositionRegister = false; |
34 | bool leadingVertexFirst = false; // Flat shading uses first vertex, else last |
35 | bool secondaryColor = false; // Specular lighting is applied after texturing |
36 | bool colorsDefaultToZero = false; |
37 | |
38 | bool forceWindowed = false; |
39 | bool quadLayoutEnabled = false; |
40 | bool veryEarlyDepthTest = true; |
41 | bool complementaryDepthBuffer = false; |
42 | bool postBlendSRGB = false; |
43 | bool exactColorRounding = false; |
44 | TransparencyAntialiasing transparencyAntialiasing = TRANSPARENCY_NONE; |
45 | bool forceClearRegisters = false; |
46 | |
47 | Context::Context() |
48 | { |
49 | init(); |
50 | } |
51 | |
52 | Context::~Context() |
53 | { |
54 | } |
55 | |
56 | void *Context::operator new(size_t bytes) |
57 | { |
58 | return allocate((unsigned int)bytes); |
59 | } |
60 | |
61 | void Context::operator delete(void *pointer, size_t bytes) |
62 | { |
63 | deallocate(pointer); |
64 | } |
65 | |
66 | bool Context::isDrawPoint(bool fillModeAware) const |
67 | { |
68 | switch(drawType) |
69 | { |
70 | case DRAW_POINTLIST: |
71 | case DRAW_INDEXEDPOINTLIST8: |
72 | case DRAW_INDEXEDPOINTLIST16: |
73 | case DRAW_INDEXEDPOINTLIST32: |
74 | return true; |
75 | case DRAW_LINELIST: |
76 | case DRAW_LINESTRIP: |
77 | case DRAW_LINELOOP: |
78 | case DRAW_INDEXEDLINELIST8: |
79 | case DRAW_INDEXEDLINESTRIP8: |
80 | case DRAW_INDEXEDLINELOOP8: |
81 | case DRAW_INDEXEDLINELIST16: |
82 | case DRAW_INDEXEDLINESTRIP16: |
83 | case DRAW_INDEXEDLINELOOP16: |
84 | case DRAW_INDEXEDLINELIST32: |
85 | case DRAW_INDEXEDLINESTRIP32: |
86 | case DRAW_INDEXEDLINELOOP32: |
87 | return false; |
88 | case DRAW_TRIANGLELIST: |
89 | case DRAW_TRIANGLESTRIP: |
90 | case DRAW_TRIANGLEFAN: |
91 | case DRAW_INDEXEDTRIANGLELIST8: |
92 | case DRAW_INDEXEDTRIANGLESTRIP8: |
93 | case DRAW_INDEXEDTRIANGLEFAN8: |
94 | case DRAW_INDEXEDTRIANGLELIST16: |
95 | case DRAW_INDEXEDTRIANGLESTRIP16: |
96 | case DRAW_INDEXEDTRIANGLEFAN16: |
97 | case DRAW_INDEXEDTRIANGLELIST32: |
98 | case DRAW_INDEXEDTRIANGLESTRIP32: |
99 | case DRAW_INDEXEDTRIANGLEFAN32: |
100 | return fillModeAware ? fillMode == FILL_VERTEX : false; |
101 | case DRAW_QUADLIST: |
102 | return false; |
103 | default: |
104 | ASSERT(false); |
105 | } |
106 | |
107 | return false; |
108 | } |
109 | |
110 | bool Context::isDrawLine(bool fillModeAware) const |
111 | { |
112 | switch(drawType) |
113 | { |
114 | case DRAW_POINTLIST: |
115 | case DRAW_INDEXEDPOINTLIST8: |
116 | case DRAW_INDEXEDPOINTLIST16: |
117 | case DRAW_INDEXEDPOINTLIST32: |
118 | return false; |
119 | case DRAW_LINELIST: |
120 | case DRAW_LINESTRIP: |
121 | case DRAW_LINELOOP: |
122 | case DRAW_INDEXEDLINELIST8: |
123 | case DRAW_INDEXEDLINESTRIP8: |
124 | case DRAW_INDEXEDLINELOOP8: |
125 | case DRAW_INDEXEDLINELIST16: |
126 | case DRAW_INDEXEDLINESTRIP16: |
127 | case DRAW_INDEXEDLINELOOP16: |
128 | case DRAW_INDEXEDLINELIST32: |
129 | case DRAW_INDEXEDLINESTRIP32: |
130 | case DRAW_INDEXEDLINELOOP32: |
131 | return true; |
132 | case DRAW_TRIANGLELIST: |
133 | case DRAW_TRIANGLESTRIP: |
134 | case DRAW_TRIANGLEFAN: |
135 | case DRAW_INDEXEDTRIANGLELIST8: |
136 | case DRAW_INDEXEDTRIANGLESTRIP8: |
137 | case DRAW_INDEXEDTRIANGLEFAN8: |
138 | case DRAW_INDEXEDTRIANGLELIST16: |
139 | case DRAW_INDEXEDTRIANGLESTRIP16: |
140 | case DRAW_INDEXEDTRIANGLEFAN16: |
141 | case DRAW_INDEXEDTRIANGLELIST32: |
142 | case DRAW_INDEXEDTRIANGLESTRIP32: |
143 | case DRAW_INDEXEDTRIANGLEFAN32: |
144 | return fillModeAware ? fillMode == FILL_WIREFRAME : false; |
145 | case DRAW_QUADLIST: |
146 | return false; |
147 | default: |
148 | ASSERT(false); |
149 | } |
150 | |
151 | return false; |
152 | } |
153 | |
154 | bool Context::isDrawTriangle(bool fillModeAware) const |
155 | { |
156 | switch(drawType) |
157 | { |
158 | case DRAW_POINTLIST: |
159 | case DRAW_INDEXEDPOINTLIST8: |
160 | case DRAW_INDEXEDPOINTLIST16: |
161 | case DRAW_INDEXEDPOINTLIST32: |
162 | return false; |
163 | case DRAW_LINELIST: |
164 | case DRAW_LINESTRIP: |
165 | case DRAW_LINELOOP: |
166 | case DRAW_INDEXEDLINELIST8: |
167 | case DRAW_INDEXEDLINESTRIP8: |
168 | case DRAW_INDEXEDLINELOOP8: |
169 | case DRAW_INDEXEDLINELIST16: |
170 | case DRAW_INDEXEDLINESTRIP16: |
171 | case DRAW_INDEXEDLINELOOP16: |
172 | case DRAW_INDEXEDLINELIST32: |
173 | case DRAW_INDEXEDLINESTRIP32: |
174 | case DRAW_INDEXEDLINELOOP32: |
175 | return false; |
176 | case DRAW_TRIANGLELIST: |
177 | case DRAW_TRIANGLESTRIP: |
178 | case DRAW_TRIANGLEFAN: |
179 | case DRAW_INDEXEDTRIANGLELIST8: |
180 | case DRAW_INDEXEDTRIANGLESTRIP8: |
181 | case DRAW_INDEXEDTRIANGLEFAN8: |
182 | case DRAW_INDEXEDTRIANGLELIST16: |
183 | case DRAW_INDEXEDTRIANGLESTRIP16: |
184 | case DRAW_INDEXEDTRIANGLEFAN16: |
185 | case DRAW_INDEXEDTRIANGLELIST32: |
186 | case DRAW_INDEXEDTRIANGLESTRIP32: |
187 | case DRAW_INDEXEDTRIANGLEFAN32: |
188 | return fillModeAware ? fillMode == FILL_SOLID : true; |
189 | case DRAW_QUADLIST: |
190 | // Quads are broken up into triangles |
191 | return fillModeAware ? fillMode == FILL_SOLID : true; |
192 | default: |
193 | ASSERT(false); |
194 | } |
195 | |
196 | return true; |
197 | } |
198 | |
199 | void Context::init() |
200 | { |
201 | for(int i = 0; i < 8; i++) |
202 | { |
203 | textureStage[i].init(i, &sampler[i], (i >= 1) ? &textureStage[i - 1] : 0); |
204 | } |
205 | |
206 | // Set vertex streams to null stream |
207 | for(int i = 0; i < MAX_VERTEX_INPUTS; i++) |
208 | { |
209 | input[i].defaults(); |
210 | } |
211 | |
212 | fogStart = 0.0f; |
213 | fogEnd = 1.0f; |
214 | |
215 | for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++) textureWrap[i] = 0; |
216 | for(int i = 0; i < 8; i++) texGen[i] = TEXGEN_PASSTHRU; |
217 | for(int i = 0; i < 8; i++) textureTransformCount[i] = 0; |
218 | for(int i = 0; i < 8; i++) textureTransformProject[i] = false; |
219 | textureWrapActive = false; |
220 | localViewer = true; |
221 | normalizeNormals = false; |
222 | |
223 | for(int i = 0; i < RENDERTARGETS; ++i) |
224 | { |
225 | renderTarget[i] = nullptr; |
226 | } |
227 | depthBuffer = nullptr; |
228 | stencilBuffer = nullptr; |
229 | |
230 | stencilEnable = false; |
231 | stencilCompareMode = STENCIL_ALWAYS; |
232 | stencilReference = 0; |
233 | stencilMask = 0xFFFFFFFF; |
234 | stencilFailOperation = OPERATION_KEEP; |
235 | stencilPassOperation = OPERATION_KEEP; |
236 | stencilZFailOperation = OPERATION_KEEP; |
237 | stencilWriteMask = 0xFFFFFFFF; |
238 | |
239 | twoSidedStencil = false; |
240 | stencilCompareModeCCW = STENCIL_ALWAYS; |
241 | stencilReferenceCCW = 0; |
242 | stencilMaskCCW = 0xFFFFFFFF; |
243 | stencilFailOperationCCW = OPERATION_KEEP; |
244 | stencilPassOperationCCW = OPERATION_KEEP; |
245 | stencilZFailOperationCCW = OPERATION_KEEP; |
246 | stencilWriteMaskCCW = 0xFFFFFFFF; |
247 | |
248 | setGlobalMipmapBias(0); |
249 | |
250 | lightingEnable = true; |
251 | specularEnable = false; |
252 | for(int i = 0; i < 8; i++) lightEnable[i] = false; |
253 | for(int i = 0; i < 8; i++) worldLightPosition[i] = 0; |
254 | |
255 | alphaCompareMode = ALPHA_ALWAYS; |
256 | alphaTestEnable = false; |
257 | fillMode = FILL_SOLID; |
258 | shadingMode = SHADING_GOURAUD; |
259 | |
260 | rasterizerDiscard = false; |
261 | |
262 | depthCompareMode = DEPTH_LESS; |
263 | depthBufferEnable = true; |
264 | depthWriteEnable = true; |
265 | |
266 | alphaBlendEnable = false; |
267 | sourceBlendFactorState = BLEND_ONE; |
268 | destBlendFactorState = BLEND_ZERO; |
269 | blendOperationState = BLENDOP_ADD; |
270 | |
271 | separateAlphaBlendEnable = false; |
272 | sourceBlendFactorStateAlpha = BLEND_ONE; |
273 | destBlendFactorStateAlpha = BLEND_ZERO; |
274 | blendOperationStateAlpha = BLENDOP_ADD; |
275 | |
276 | cullMode = CULL_CLOCKWISE; |
277 | frontFacingCCW = true; |
278 | alphaReference = 0.0f; |
279 | |
280 | depthBias = 0.0f; |
281 | slopeDepthBias = 0.0f; |
282 | |
283 | for(int i = 0; i < RENDERTARGETS; i++) |
284 | { |
285 | colorWriteMask[i] = 0x0000000F; |
286 | } |
287 | |
288 | ambientMaterialSource = MATERIAL_MATERIAL; |
289 | diffuseMaterialSource = MATERIAL_COLOR1; |
290 | specularMaterialSource = MATERIAL_COLOR2; |
291 | emissiveMaterialSource = MATERIAL_MATERIAL; |
292 | colorVertexEnable = true; |
293 | |
294 | fogEnable = false; |
295 | pixelFogMode = FOG_NONE; |
296 | vertexFogMode = FOG_NONE; |
297 | wBasedFog = false; |
298 | rangeFogEnable = false; |
299 | |
300 | indexedVertexBlendEnable = false; |
301 | vertexBlendMatrixCount = 0; |
302 | |
303 | pixelShader = 0; |
304 | vertexShader = 0; |
305 | |
306 | instanceID = 0; |
307 | |
308 | occlusionEnabled = false; |
309 | transformFeedbackQueryEnabled = false; |
310 | transformFeedbackEnabled = 0; |
311 | |
312 | pointSpriteEnable = false; |
313 | pointScaleEnable = false; |
314 | lineWidth = 1.0f; |
315 | |
316 | writeSRGB = false; |
317 | sampleMask = 0xFFFFFFFF; |
318 | |
319 | colorLogicOpEnabled = false; |
320 | logicalOperation = LOGICALOP_COPY; |
321 | } |
322 | |
323 | const float &Context::exp2Bias() |
324 | { |
325 | return bias; |
326 | } |
327 | |
328 | const Point &Context::getLightPosition(int light) |
329 | { |
330 | return worldLightPosition[light]; |
331 | } |
332 | |
333 | void Context::setGlobalMipmapBias(float bias) |
334 | { |
335 | this->bias = exp2(bias + 0.5f); |
336 | } |
337 | |
338 | void Context::setLightingEnable(bool lightingEnable) |
339 | { |
340 | this->lightingEnable = lightingEnable; |
341 | } |
342 | |
343 | void Context::setSpecularEnable(bool specularEnable) |
344 | { |
345 | Context::specularEnable = specularEnable; |
346 | } |
347 | |
348 | void Context::setLightEnable(int light, bool lightEnable) |
349 | { |
350 | Context::lightEnable[light] = lightEnable; |
351 | } |
352 | |
353 | void Context::setLightPosition(int light, Point worldLightPosition) |
354 | { |
355 | Context::worldLightPosition[light] = worldLightPosition; |
356 | } |
357 | |
358 | void Context::setAmbientMaterialSource(MaterialSource ambientMaterialSource) |
359 | { |
360 | Context::ambientMaterialSource = ambientMaterialSource; |
361 | } |
362 | |
363 | void Context::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource) |
364 | { |
365 | Context::diffuseMaterialSource = diffuseMaterialSource; |
366 | } |
367 | |
368 | void Context::setSpecularMaterialSource(MaterialSource specularMaterialSource) |
369 | { |
370 | Context::specularMaterialSource = specularMaterialSource; |
371 | } |
372 | |
373 | void Context::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource) |
374 | { |
375 | Context::emissiveMaterialSource = emissiveMaterialSource; |
376 | } |
377 | |
378 | void Context::setPointSpriteEnable(bool pointSpriteEnable) |
379 | { |
380 | Context::pointSpriteEnable = pointSpriteEnable; |
381 | } |
382 | |
383 | void Context::setPointScaleEnable(bool pointScaleEnable) |
384 | { |
385 | Context::pointScaleEnable = pointScaleEnable; |
386 | } |
387 | |
388 | bool Context::setDepthBufferEnable(bool depthBufferEnable) |
389 | { |
390 | bool modified = (Context::depthBufferEnable != depthBufferEnable); |
391 | Context::depthBufferEnable = depthBufferEnable; |
392 | return modified; |
393 | } |
394 | |
395 | bool Context::setAlphaBlendEnable(bool alphaBlendEnable) |
396 | { |
397 | bool modified = (Context::alphaBlendEnable != alphaBlendEnable); |
398 | Context::alphaBlendEnable = alphaBlendEnable; |
399 | return modified; |
400 | } |
401 | |
402 | bool Context::setSourceBlendFactor(BlendFactor sourceBlendFactor) |
403 | { |
404 | bool modified = (Context::sourceBlendFactorState != sourceBlendFactor); |
405 | Context::sourceBlendFactorState = sourceBlendFactor; |
406 | return modified; |
407 | } |
408 | |
409 | bool Context::setDestBlendFactor(BlendFactor destBlendFactor) |
410 | { |
411 | bool modified = (Context::destBlendFactorState != destBlendFactor); |
412 | Context::destBlendFactorState = destBlendFactor; |
413 | return modified; |
414 | } |
415 | |
416 | bool Context::setBlendOperation(BlendOperation blendOperation) |
417 | { |
418 | bool modified = (Context::blendOperationState != blendOperation); |
419 | Context::blendOperationState = blendOperation; |
420 | return modified; |
421 | } |
422 | |
423 | bool Context::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable) |
424 | { |
425 | bool modified = (Context::separateAlphaBlendEnable != separateAlphaBlendEnable); |
426 | Context::separateAlphaBlendEnable = separateAlphaBlendEnable; |
427 | return modified; |
428 | } |
429 | |
430 | bool Context::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha) |
431 | { |
432 | bool modified = (Context::sourceBlendFactorStateAlpha != sourceBlendFactorAlpha); |
433 | Context::sourceBlendFactorStateAlpha = sourceBlendFactorAlpha; |
434 | return modified; |
435 | } |
436 | |
437 | bool Context::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha) |
438 | { |
439 | bool modified = (Context::destBlendFactorStateAlpha != destBlendFactorAlpha); |
440 | Context::destBlendFactorStateAlpha = destBlendFactorAlpha; |
441 | return modified; |
442 | } |
443 | |
444 | bool Context::setBlendOperationAlpha(BlendOperation blendOperationAlpha) |
445 | { |
446 | bool modified = (Context::blendOperationStateAlpha != blendOperationAlpha); |
447 | Context::blendOperationStateAlpha = blendOperationAlpha; |
448 | return modified; |
449 | } |
450 | |
451 | bool Context::setColorWriteMask(int index, int colorWriteMask) |
452 | { |
453 | bool modified = (Context::colorWriteMask[index] != colorWriteMask); |
454 | Context::colorWriteMask[index] = colorWriteMask; |
455 | return modified; |
456 | } |
457 | |
458 | bool Context::setWriteSRGB(bool sRGB) |
459 | { |
460 | bool modified = (Context::writeSRGB != sRGB); |
461 | Context::writeSRGB = sRGB; |
462 | return modified; |
463 | } |
464 | |
465 | bool Context::setColorLogicOpEnabled(bool enabled) |
466 | { |
467 | bool modified = (Context::colorLogicOpEnabled != enabled); |
468 | Context::colorLogicOpEnabled = enabled; |
469 | return modified; |
470 | } |
471 | |
472 | bool Context::setLogicalOperation(LogicalOperation logicalOperation) |
473 | { |
474 | bool modified = (Context::logicalOperation != logicalOperation); |
475 | Context::logicalOperation = logicalOperation; |
476 | return modified; |
477 | } |
478 | |
479 | void Context::setColorVertexEnable(bool colorVertexEnable) |
480 | { |
481 | Context::colorVertexEnable = colorVertexEnable; |
482 | } |
483 | |
484 | bool Context::fogActive() |
485 | { |
486 | if(!colorUsed()) return false; |
487 | |
488 | if(pixelShaderModel() >= 0x0300) return false; |
489 | |
490 | return fogEnable; |
491 | } |
492 | |
493 | bool Context::pointSizeActive() |
494 | { |
495 | if(vertexShader) |
496 | { |
497 | return false; |
498 | } |
499 | |
500 | return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive())); |
501 | } |
502 | |
503 | FogMode Context::pixelFogActive() |
504 | { |
505 | if(fogActive()) |
506 | { |
507 | return pixelFogMode; |
508 | } |
509 | |
510 | return FOG_NONE; |
511 | } |
512 | |
513 | bool Context::depthWriteActive() |
514 | { |
515 | if(!depthBufferActive()) return false; |
516 | |
517 | return depthWriteEnable; |
518 | } |
519 | |
520 | bool Context::alphaTestActive() |
521 | { |
522 | if(transparencyAntialiasing != TRANSPARENCY_NONE) return true; |
523 | if(!alphaTestEnable) return false; |
524 | if(alphaCompareMode == ALPHA_ALWAYS) return false; |
525 | if(alphaReference == 0.0f && alphaCompareMode == ALPHA_GREATEREQUAL) return false; |
526 | |
527 | return true; |
528 | } |
529 | |
530 | bool Context::depthBufferActive() |
531 | { |
532 | return depthBuffer && depthBufferEnable; |
533 | } |
534 | |
535 | bool Context::stencilActive() |
536 | { |
537 | return stencilBuffer && stencilEnable; |
538 | } |
539 | |
540 | bool Context::vertexLightingActive() |
541 | { |
542 | if(vertexShader) |
543 | { |
544 | return false; |
545 | } |
546 | |
547 | return lightingEnable && !preTransformed; |
548 | } |
549 | |
550 | bool Context::texCoordActive(int coordinate, int component) |
551 | { |
552 | bool hasTexture = pointSpriteActive(); |
553 | |
554 | if(vertexShader) |
555 | { |
556 | if(!preTransformed) |
557 | { |
558 | if(vertexShader->getOutput(T0 + coordinate, component).usage == Shader::USAGE_TEXCOORD) |
559 | { |
560 | hasTexture = true; |
561 | } |
562 | } |
563 | else |
564 | { |
565 | hasTexture = true; // FIXME: Check vertex buffer streams |
566 | } |
567 | } |
568 | else |
569 | { |
570 | switch(texGen[coordinate]) |
571 | { |
572 | case TEXGEN_NONE: |
573 | hasTexture = true; |
574 | break; |
575 | case TEXGEN_PASSTHRU: |
576 | hasTexture = hasTexture || (component < input[TexCoord0 + textureStage[coordinate].texCoordIndex].count); |
577 | break; |
578 | case TEXGEN_NORMAL: |
579 | hasTexture = hasTexture || (component <= 2); |
580 | break; |
581 | case TEXGEN_POSITION: |
582 | hasTexture = hasTexture || (component <= 2); |
583 | break; |
584 | case TEXGEN_REFLECTION: |
585 | hasTexture = hasTexture || (component <= 2); |
586 | break; |
587 | case TEXGEN_SPHEREMAP: |
588 | hasTexture = hasTexture || (component <= 1); |
589 | break; |
590 | default: |
591 | ASSERT(false); |
592 | } |
593 | } |
594 | |
595 | bool project = isProjectionComponent(coordinate, component); |
596 | bool usesTexture = false; |
597 | |
598 | if(pixelShader) |
599 | { |
600 | usesTexture = pixelShader->usesTexture(coordinate, component) || project; |
601 | } |
602 | else |
603 | { |
604 | usesTexture = textureStage[coordinate].usesTexture() || project; |
605 | } |
606 | |
607 | return hasTexture && usesTexture; |
608 | } |
609 | |
610 | bool Context::texCoordActive(int coordinate) |
611 | { |
612 | return texCoordActive(coordinate, 0) || |
613 | texCoordActive(coordinate, 1) || |
614 | texCoordActive(coordinate, 2) || |
615 | texCoordActive(coordinate, 3); |
616 | } |
617 | |
618 | bool Context::isProjectionComponent(unsigned int coordinate, int component) |
619 | { |
620 | if(pixelShaderModel() <= 0x0103 && coordinate < 8 && textureTransformProject[coordinate]) |
621 | { |
622 | if(textureTransformCount[coordinate] == 2) |
623 | { |
624 | if(component == 1) return true; |
625 | } |
626 | else if(textureTransformCount[coordinate] == 3) |
627 | { |
628 | if(component == 2) return true; |
629 | } |
630 | else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0) |
631 | { |
632 | if(component == 3) return true; |
633 | } |
634 | } |
635 | |
636 | return false; |
637 | } |
638 | |
639 | bool Context::vertexSpecularActive() |
640 | { |
641 | return vertexLightingActive() && specularEnable && vertexNormalActive(); |
642 | } |
643 | |
644 | bool Context::vertexNormalActive() |
645 | { |
646 | if(vertexShader) |
647 | { |
648 | return false; |
649 | } |
650 | |
651 | return input[Normal]; |
652 | } |
653 | |
654 | bool Context::vertexLightActive(int i) |
655 | { |
656 | if(vertexShader) |
657 | { |
658 | return false; |
659 | } |
660 | |
661 | return lightingEnable && lightEnable[i]; |
662 | } |
663 | |
664 | MaterialSource Context::vertexDiffuseMaterialSourceActive() |
665 | { |
666 | if(vertexShader) |
667 | { |
668 | return MATERIAL_MATERIAL; |
669 | } |
670 | |
671 | if(diffuseMaterialSource == MATERIAL_MATERIAL || !colorVertexEnable || |
672 | (diffuseMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || |
673 | (diffuseMaterialSource == MATERIAL_COLOR2 && !input[Color1])) |
674 | { |
675 | return MATERIAL_MATERIAL; |
676 | } |
677 | |
678 | return diffuseMaterialSource; |
679 | } |
680 | |
681 | MaterialSource Context::vertexSpecularMaterialSourceActive() |
682 | { |
683 | if(vertexShader) |
684 | { |
685 | return MATERIAL_MATERIAL; |
686 | } |
687 | |
688 | if(!colorVertexEnable || |
689 | (specularMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || |
690 | (specularMaterialSource == MATERIAL_COLOR2 && !input[Color1])) |
691 | { |
692 | return MATERIAL_MATERIAL; |
693 | } |
694 | |
695 | return specularMaterialSource; |
696 | } |
697 | |
698 | MaterialSource Context::vertexAmbientMaterialSourceActive() |
699 | { |
700 | if(vertexShader) |
701 | { |
702 | return MATERIAL_MATERIAL; |
703 | } |
704 | |
705 | if(!colorVertexEnable || |
706 | (ambientMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || |
707 | (ambientMaterialSource == MATERIAL_COLOR2 && !input[Color1])) |
708 | { |
709 | return MATERIAL_MATERIAL; |
710 | } |
711 | |
712 | return ambientMaterialSource; |
713 | } |
714 | |
715 | MaterialSource Context::vertexEmissiveMaterialSourceActive() |
716 | { |
717 | if(vertexShader) |
718 | { |
719 | return MATERIAL_MATERIAL; |
720 | } |
721 | |
722 | if(!colorVertexEnable || |
723 | (emissiveMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || |
724 | (emissiveMaterialSource == MATERIAL_COLOR2 && !input[Color1])) |
725 | { |
726 | return MATERIAL_MATERIAL; |
727 | } |
728 | |
729 | return emissiveMaterialSource; |
730 | } |
731 | |
732 | bool Context::pointSpriteActive() |
733 | { |
734 | return isDrawPoint(true) && pointSpriteEnable; |
735 | } |
736 | |
737 | bool Context::pointScaleActive() |
738 | { |
739 | if(vertexShader) |
740 | { |
741 | return false; |
742 | } |
743 | |
744 | return isDrawPoint(true) && pointScaleEnable; |
745 | } |
746 | |
747 | bool Context::alphaBlendActive() |
748 | { |
749 | if(!alphaBlendEnable) |
750 | { |
751 | return false; |
752 | } |
753 | |
754 | if(!colorUsed()) |
755 | { |
756 | return false; |
757 | } |
758 | |
759 | bool colorBlend = !(blendOperation() == BLENDOP_SOURCE && sourceBlendFactor() == BLEND_ONE); |
760 | bool alphaBlend = separateAlphaBlendEnable ? !(blendOperationAlpha() == BLENDOP_SOURCE && sourceBlendFactorAlpha() == BLEND_ONE) : colorBlend; |
761 | |
762 | return colorBlend || alphaBlend; |
763 | } |
764 | |
765 | LogicalOperation Context::colorLogicOp() |
766 | { |
767 | return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY; |
768 | } |
769 | |
770 | BlendFactor Context::sourceBlendFactor() |
771 | { |
772 | if(!alphaBlendEnable) return BLEND_ONE; |
773 | |
774 | switch(blendOperationState) |
775 | { |
776 | case BLENDOP_ADD: |
777 | case BLENDOP_SUB: |
778 | case BLENDOP_INVSUB: |
779 | return sourceBlendFactorState; |
780 | case BLENDOP_MIN: |
781 | return BLEND_ONE; |
782 | case BLENDOP_MAX: |
783 | return BLEND_ONE; |
784 | default: |
785 | ASSERT(false); |
786 | } |
787 | |
788 | return sourceBlendFactorState; |
789 | } |
790 | |
791 | BlendFactor Context::destBlendFactor() |
792 | { |
793 | if(!alphaBlendEnable) return BLEND_ZERO; |
794 | |
795 | switch(blendOperationState) |
796 | { |
797 | case BLENDOP_ADD: |
798 | case BLENDOP_SUB: |
799 | case BLENDOP_INVSUB: |
800 | return destBlendFactorState; |
801 | case BLENDOP_MIN: |
802 | return BLEND_ONE; |
803 | case BLENDOP_MAX: |
804 | return BLEND_ONE; |
805 | default: |
806 | ASSERT(false); |
807 | } |
808 | |
809 | return destBlendFactorState; |
810 | } |
811 | |
812 | BlendOperation Context::blendOperation() |
813 | { |
814 | if(!alphaBlendEnable) return BLENDOP_SOURCE; |
815 | |
816 | switch(blendOperationState) |
817 | { |
818 | case BLENDOP_ADD: |
819 | if(sourceBlendFactor() == BLEND_ZERO) |
820 | { |
821 | if(destBlendFactor() == BLEND_ZERO) |
822 | { |
823 | return BLENDOP_NULL; |
824 | } |
825 | else |
826 | { |
827 | return BLENDOP_DEST; |
828 | } |
829 | } |
830 | else if(sourceBlendFactor() == BLEND_ONE) |
831 | { |
832 | if(destBlendFactor() == BLEND_ZERO) |
833 | { |
834 | return BLENDOP_SOURCE; |
835 | } |
836 | else |
837 | { |
838 | return BLENDOP_ADD; |
839 | } |
840 | } |
841 | else |
842 | { |
843 | if(destBlendFactor() == BLEND_ZERO) |
844 | { |
845 | return BLENDOP_SOURCE; |
846 | } |
847 | else |
848 | { |
849 | return BLENDOP_ADD; |
850 | } |
851 | } |
852 | case BLENDOP_SUB: |
853 | if(sourceBlendFactor() == BLEND_ZERO) |
854 | { |
855 | return BLENDOP_NULL; // Negative, clamped to zero |
856 | } |
857 | else if(sourceBlendFactor() == BLEND_ONE) |
858 | { |
859 | if(destBlendFactor() == BLEND_ZERO) |
860 | { |
861 | return BLENDOP_SOURCE; |
862 | } |
863 | else |
864 | { |
865 | return BLENDOP_SUB; |
866 | } |
867 | } |
868 | else |
869 | { |
870 | if(destBlendFactor() == BLEND_ZERO) |
871 | { |
872 | return BLENDOP_SOURCE; |
873 | } |
874 | else |
875 | { |
876 | return BLENDOP_SUB; |
877 | } |
878 | } |
879 | case BLENDOP_INVSUB: |
880 | if(sourceBlendFactor() == BLEND_ZERO) |
881 | { |
882 | if(destBlendFactor() == BLEND_ZERO) |
883 | { |
884 | return BLENDOP_NULL; |
885 | } |
886 | else |
887 | { |
888 | return BLENDOP_DEST; |
889 | } |
890 | } |
891 | else if(sourceBlendFactor() == BLEND_ONE) |
892 | { |
893 | if(destBlendFactor() == BLEND_ZERO) |
894 | { |
895 | return BLENDOP_NULL; // Negative, clamped to zero |
896 | } |
897 | else |
898 | { |
899 | return BLENDOP_INVSUB; |
900 | } |
901 | } |
902 | else |
903 | { |
904 | if(destBlendFactor() == BLEND_ZERO) |
905 | { |
906 | return BLENDOP_NULL; // Negative, clamped to zero |
907 | } |
908 | else |
909 | { |
910 | return BLENDOP_INVSUB; |
911 | } |
912 | } |
913 | case BLENDOP_MIN: |
914 | return BLENDOP_MIN; |
915 | case BLENDOP_MAX: |
916 | return BLENDOP_MAX; |
917 | default: |
918 | ASSERT(false); |
919 | } |
920 | |
921 | return blendOperationState; |
922 | } |
923 | |
924 | BlendFactor Context::sourceBlendFactorAlpha() |
925 | { |
926 | if(!separateAlphaBlendEnable) |
927 | { |
928 | return sourceBlendFactor(); |
929 | } |
930 | else |
931 | { |
932 | switch(blendOperationStateAlpha) |
933 | { |
934 | case BLENDOP_ADD: |
935 | case BLENDOP_SUB: |
936 | case BLENDOP_INVSUB: |
937 | return sourceBlendFactorStateAlpha; |
938 | case BLENDOP_MIN: |
939 | return BLEND_ONE; |
940 | case BLENDOP_MAX: |
941 | return BLEND_ONE; |
942 | default: |
943 | ASSERT(false); |
944 | } |
945 | |
946 | return sourceBlendFactorStateAlpha; |
947 | } |
948 | } |
949 | |
950 | BlendFactor Context::destBlendFactorAlpha() |
951 | { |
952 | if(!separateAlphaBlendEnable) |
953 | { |
954 | return destBlendFactor(); |
955 | } |
956 | else |
957 | { |
958 | switch(blendOperationStateAlpha) |
959 | { |
960 | case BLENDOP_ADD: |
961 | case BLENDOP_SUB: |
962 | case BLENDOP_INVSUB: |
963 | return destBlendFactorStateAlpha; |
964 | case BLENDOP_MIN: |
965 | return BLEND_ONE; |
966 | case BLENDOP_MAX: |
967 | return BLEND_ONE; |
968 | default: |
969 | ASSERT(false); |
970 | } |
971 | |
972 | return destBlendFactorStateAlpha; |
973 | } |
974 | } |
975 | |
976 | BlendOperation Context::blendOperationAlpha() |
977 | { |
978 | if(!separateAlphaBlendEnable) |
979 | { |
980 | return blendOperation(); |
981 | } |
982 | else |
983 | { |
984 | switch(blendOperationStateAlpha) |
985 | { |
986 | case BLENDOP_ADD: |
987 | if(sourceBlendFactorAlpha() == BLEND_ZERO) |
988 | { |
989 | if(destBlendFactorAlpha() == BLEND_ZERO) |
990 | { |
991 | return BLENDOP_NULL; |
992 | } |
993 | else |
994 | { |
995 | return BLENDOP_DEST; |
996 | } |
997 | } |
998 | else if(sourceBlendFactorAlpha() == BLEND_ONE) |
999 | { |
1000 | if(destBlendFactorAlpha() == BLEND_ZERO) |
1001 | { |
1002 | return BLENDOP_SOURCE; |
1003 | } |
1004 | else |
1005 | { |
1006 | return BLENDOP_ADD; |
1007 | } |
1008 | } |
1009 | else |
1010 | { |
1011 | if(destBlendFactorAlpha() == BLEND_ZERO) |
1012 | { |
1013 | return BLENDOP_SOURCE; |
1014 | } |
1015 | else |
1016 | { |
1017 | return BLENDOP_ADD; |
1018 | } |
1019 | } |
1020 | case BLENDOP_SUB: |
1021 | if(sourceBlendFactorAlpha() == BLEND_ZERO) |
1022 | { |
1023 | return BLENDOP_NULL; // Negative, clamped to zero |
1024 | } |
1025 | else if(sourceBlendFactorAlpha() == BLEND_ONE) |
1026 | { |
1027 | if(destBlendFactorAlpha() == BLEND_ZERO) |
1028 | { |
1029 | return BLENDOP_SOURCE; |
1030 | } |
1031 | else |
1032 | { |
1033 | return BLENDOP_SUB; |
1034 | } |
1035 | } |
1036 | else |
1037 | { |
1038 | if(destBlendFactorAlpha() == BLEND_ZERO) |
1039 | { |
1040 | return BLENDOP_SOURCE; |
1041 | } |
1042 | else |
1043 | { |
1044 | return BLENDOP_SUB; |
1045 | } |
1046 | } |
1047 | case BLENDOP_INVSUB: |
1048 | if(sourceBlendFactorAlpha() == BLEND_ZERO) |
1049 | { |
1050 | if(destBlendFactorAlpha() == BLEND_ZERO) |
1051 | { |
1052 | return BLENDOP_NULL; |
1053 | } |
1054 | else |
1055 | { |
1056 | return BLENDOP_DEST; |
1057 | } |
1058 | } |
1059 | else if(sourceBlendFactorAlpha() == BLEND_ONE) |
1060 | { |
1061 | if(destBlendFactorAlpha() == BLEND_ZERO) |
1062 | { |
1063 | return BLENDOP_NULL; // Negative, clamped to zero |
1064 | } |
1065 | else |
1066 | { |
1067 | return BLENDOP_INVSUB; |
1068 | } |
1069 | } |
1070 | else |
1071 | { |
1072 | if(destBlendFactorAlpha() == BLEND_ZERO) |
1073 | { |
1074 | return BLENDOP_NULL; // Negative, clamped to zero |
1075 | } |
1076 | else |
1077 | { |
1078 | return BLENDOP_INVSUB; |
1079 | } |
1080 | } |
1081 | case BLENDOP_MIN: |
1082 | return BLENDOP_MIN; |
1083 | case BLENDOP_MAX: |
1084 | return BLENDOP_MAX; |
1085 | default: |
1086 | ASSERT(false); |
1087 | } |
1088 | |
1089 | return blendOperationStateAlpha; |
1090 | } |
1091 | } |
1092 | |
1093 | bool Context::indexedVertexBlendActive() |
1094 | { |
1095 | if(vertexShader) |
1096 | { |
1097 | return false; |
1098 | } |
1099 | |
1100 | return indexedVertexBlendEnable; |
1101 | } |
1102 | |
1103 | int Context::vertexBlendMatrixCountActive() |
1104 | { |
1105 | if(vertexShader) |
1106 | { |
1107 | return 0; |
1108 | } |
1109 | |
1110 | return vertexBlendMatrixCount; |
1111 | } |
1112 | |
1113 | bool Context::localViewerActive() |
1114 | { |
1115 | if(vertexShader) |
1116 | { |
1117 | return false; |
1118 | } |
1119 | |
1120 | return localViewer; |
1121 | } |
1122 | |
1123 | bool Context::normalizeNormalsActive() |
1124 | { |
1125 | if(vertexShader) |
1126 | { |
1127 | return false; |
1128 | } |
1129 | |
1130 | return normalizeNormals; |
1131 | } |
1132 | |
1133 | FogMode Context::vertexFogModeActive() |
1134 | { |
1135 | if(vertexShader || !fogActive()) |
1136 | { |
1137 | return FOG_NONE; |
1138 | } |
1139 | |
1140 | return vertexFogMode; |
1141 | } |
1142 | |
1143 | bool Context::rangeFogActive() |
1144 | { |
1145 | if(vertexShader || !fogActive()) |
1146 | { |
1147 | return false; |
1148 | } |
1149 | |
1150 | return rangeFogEnable; |
1151 | } |
1152 | |
1153 | TexGen Context::texGenActive(int stage) |
1154 | { |
1155 | if(vertexShader || !texCoordActive(stage)) |
1156 | { |
1157 | return TEXGEN_PASSTHRU; |
1158 | } |
1159 | |
1160 | return texGen[stage]; |
1161 | } |
1162 | |
1163 | int Context::textureTransformCountActive(int stage) |
1164 | { |
1165 | if(vertexShader || !texCoordActive(stage)) |
1166 | { |
1167 | return 0; |
1168 | } |
1169 | |
1170 | return textureTransformCount[stage]; |
1171 | } |
1172 | |
1173 | int Context::texCoordIndexActive(int stage) |
1174 | { |
1175 | if(vertexShader || !texCoordActive(stage)) |
1176 | { |
1177 | return stage; |
1178 | } |
1179 | |
1180 | return textureStage[stage].texCoordIndex; |
1181 | } |
1182 | |
1183 | bool Context::perspectiveActive() |
1184 | { |
1185 | if(!colorUsed()) |
1186 | { |
1187 | return false; |
1188 | } |
1189 | |
1190 | if(!perspectiveCorrection) |
1191 | { |
1192 | return false; |
1193 | } |
1194 | |
1195 | if(isDrawPoint(true)) |
1196 | { |
1197 | return false; |
1198 | } |
1199 | |
1200 | return true; |
1201 | } |
1202 | |
1203 | bool Context::diffuseUsed() |
1204 | { |
1205 | return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3); |
1206 | } |
1207 | |
1208 | bool Context::diffuseUsed(int component) |
1209 | { |
1210 | if(!colorUsed()) |
1211 | { |
1212 | return false; |
1213 | } |
1214 | |
1215 | if(pixelShader) |
1216 | { |
1217 | return pixelShader->usesDiffuse(component); |
1218 | } |
1219 | |
1220 | // Directly using the diffuse input color |
1221 | for(int i = 0; i < 8; i++) |
1222 | { |
1223 | if(textureStage[i].isStageDisabled()) |
1224 | { |
1225 | break; |
1226 | } |
1227 | |
1228 | if(textureStage[i].usesDiffuse()) |
1229 | { |
1230 | return true; |
1231 | } |
1232 | } |
1233 | |
1234 | // Using the current color (initialized to diffuse) before it's overwritten |
1235 | for(int i = 0; i < 8; i++) |
1236 | { |
1237 | if(textureStage[i].usesCurrent() || textureStage[i].isStageDisabled()) // Current color contains diffuse before being overwritten |
1238 | { |
1239 | return true; |
1240 | } |
1241 | |
1242 | if(textureStage[i].writesCurrent()) |
1243 | { |
1244 | return false; |
1245 | } |
1246 | } |
1247 | |
1248 | return true; |
1249 | } |
1250 | |
1251 | bool Context::diffuseActive() |
1252 | { |
1253 | return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3); |
1254 | } |
1255 | |
1256 | bool Context::diffuseActive(int component) |
1257 | { |
1258 | if(!colorUsed()) |
1259 | { |
1260 | return false; |
1261 | } |
1262 | |
1263 | // Vertex processor provides diffuse component |
1264 | bool vertexDiffuse; |
1265 | |
1266 | if(vertexShader) |
1267 | { |
1268 | vertexDiffuse = vertexShader->getOutput(C0, component).active(); |
1269 | } |
1270 | else if(!preTransformed) |
1271 | { |
1272 | vertexDiffuse = input[Color0] || lightingEnable; |
1273 | } |
1274 | else |
1275 | { |
1276 | vertexDiffuse = input[Color0]; |
1277 | } |
1278 | |
1279 | // Pixel processor requires diffuse component |
1280 | bool pixelDiffuse = diffuseUsed(component); |
1281 | |
1282 | return vertexDiffuse && pixelDiffuse; |
1283 | } |
1284 | |
1285 | bool Context::specularUsed() |
1286 | { |
1287 | return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3); |
1288 | } |
1289 | |
1290 | bool Context::specularUsed(int component) |
1291 | { |
1292 | if(!colorUsed()) |
1293 | { |
1294 | return false; |
1295 | } |
1296 | |
1297 | if(pixelShader) |
1298 | { |
1299 | return pixelShader->usesSpecular(component); |
1300 | } |
1301 | |
1302 | bool pixelSpecular = specularEnable; |
1303 | |
1304 | for(int i = 0; i < 8; i++) |
1305 | { |
1306 | if(textureStage[i].isStageDisabled()) break; |
1307 | |
1308 | pixelSpecular = pixelSpecular || textureStage[i].usesSpecular(); |
1309 | } |
1310 | |
1311 | return pixelSpecular; |
1312 | } |
1313 | |
1314 | bool Context::specularActive() |
1315 | { |
1316 | return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3); |
1317 | } |
1318 | |
1319 | bool Context::specularActive(int component) |
1320 | { |
1321 | if(!colorUsed()) |
1322 | { |
1323 | return false; |
1324 | } |
1325 | |
1326 | // Vertex processor provides specular component |
1327 | bool vertexSpecular; |
1328 | |
1329 | if(!vertexShader) |
1330 | { |
1331 | vertexSpecular = input[Color1] || (lightingEnable && specularEnable); |
1332 | } |
1333 | else |
1334 | { |
1335 | vertexSpecular = vertexShader->getOutput(C1, component).active(); |
1336 | } |
1337 | |
1338 | // Pixel processor requires specular component |
1339 | bool pixelSpecular = specularUsed(component); |
1340 | |
1341 | return vertexSpecular && pixelSpecular; |
1342 | } |
1343 | |
1344 | bool Context::colorActive(int color, int component) |
1345 | { |
1346 | if(color == 0) |
1347 | { |
1348 | return diffuseActive(component); |
1349 | } |
1350 | else |
1351 | { |
1352 | return specularActive(component); |
1353 | } |
1354 | } |
1355 | |
1356 | bool Context::textureActive() |
1357 | { |
1358 | for(int i = 0; i < 8; i++) |
1359 | { |
1360 | if(textureActive(i)) |
1361 | { |
1362 | return true; |
1363 | } |
1364 | } |
1365 | |
1366 | return false; |
1367 | } |
1368 | |
1369 | bool Context::textureActive(int coordinate) |
1370 | { |
1371 | return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3); |
1372 | } |
1373 | |
1374 | bool Context::textureActive(int coordinate, int component) |
1375 | { |
1376 | if(!colorUsed()) |
1377 | { |
1378 | return false; |
1379 | } |
1380 | |
1381 | if(!texCoordActive(coordinate, component)) |
1382 | { |
1383 | return false; |
1384 | } |
1385 | |
1386 | if(textureTransformProject[coordinate] && pixelShaderModel() <= 0x0103) |
1387 | { |
1388 | if(textureTransformCount[coordinate] == 2) |
1389 | { |
1390 | if(component == 1) return true; |
1391 | } |
1392 | else if(textureTransformCount[coordinate] == 3) |
1393 | { |
1394 | if(component == 2) return true; |
1395 | } |
1396 | else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0) |
1397 | { |
1398 | if(component == 3) return true; |
1399 | } |
1400 | } |
1401 | |
1402 | if(!pixelShader) |
1403 | { |
1404 | bool texture = textureStage[coordinate].usesTexture(); |
1405 | bool cube = sampler[coordinate].hasCubeTexture(); |
1406 | bool volume = sampler[coordinate].hasVolumeTexture(); |
1407 | |
1408 | if(texture) |
1409 | { |
1410 | for(int i = coordinate; i >= 0; i--) |
1411 | { |
1412 | if(textureStage[i].stageOperation == TextureStage::STAGE_DISABLE) |
1413 | { |
1414 | return false; |
1415 | } |
1416 | } |
1417 | } |
1418 | |
1419 | switch(component) |
1420 | { |
1421 | case 0: |
1422 | return texture; |
1423 | case 1: |
1424 | return texture; |
1425 | case 2: |
1426 | return (texture && (cube || volume)); |
1427 | case 3: |
1428 | return false; |
1429 | } |
1430 | } |
1431 | else |
1432 | { |
1433 | return pixelShader->usesTexture(coordinate, component); |
1434 | } |
1435 | |
1436 | return false; |
1437 | } |
1438 | |
1439 | unsigned short Context::pixelShaderModel() const |
1440 | { |
1441 | return pixelShader ? pixelShader->getShaderModel() : 0x0000; |
1442 | } |
1443 | |
1444 | unsigned short Context::vertexShaderModel() const |
1445 | { |
1446 | return vertexShader ? vertexShader->getShaderModel() : 0x0000; |
1447 | } |
1448 | |
1449 | int Context::getMultiSampleCount() const |
1450 | { |
1451 | return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1; |
1452 | } |
1453 | |
1454 | int Context::getSuperSampleCount() const |
1455 | { |
1456 | return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1; |
1457 | } |
1458 | |
1459 | Format Context::renderTargetInternalFormat(int index) |
1460 | { |
1461 | if(renderTarget[index]) |
1462 | { |
1463 | return renderTarget[index]->getInternalFormat(); |
1464 | } |
1465 | else |
1466 | { |
1467 | return FORMAT_NULL; |
1468 | } |
1469 | } |
1470 | |
1471 | bool Context::colorWriteActive() |
1472 | { |
1473 | for (int i = 0; i < RENDERTARGETS; i++) |
1474 | { |
1475 | if (colorWriteActive(i)) |
1476 | { |
1477 | return true; |
1478 | } |
1479 | } |
1480 | |
1481 | return false; |
1482 | } |
1483 | |
1484 | int Context::colorWriteActive(int index) |
1485 | { |
1486 | if(!renderTarget[index] || renderTarget[index]->getInternalFormat() == FORMAT_NULL) |
1487 | { |
1488 | return 0; |
1489 | } |
1490 | |
1491 | if(blendOperation() == BLENDOP_DEST && destBlendFactor() == BLEND_ONE && |
1492 | (!separateAlphaBlendEnable || (blendOperationAlpha() == BLENDOP_DEST && destBlendFactorAlpha() == BLEND_ONE))) |
1493 | { |
1494 | return 0; |
1495 | } |
1496 | |
1497 | return colorWriteMask[index]; |
1498 | } |
1499 | |
1500 | bool Context::colorUsed() |
1501 | { |
1502 | return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill()); |
1503 | } |
1504 | } |
1505 | |