1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Reference Rendering Context.
22 *//*--------------------------------------------------------------------*/
24 #include "sglrReferenceContext.hpp"
25 #include "sglrReferenceUtils.hpp"
26 #include "sglrShaderProgram.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "tcuMatrix.hpp"
29 #include "tcuMatrixUtil.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "gluDefs.hpp"
32 #include "gluTextureUtil.hpp"
33 #include "gluContextInfo.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
37 #include "rrFragmentOperations.hpp"
38 #include "rrRenderer.hpp"
55 // Reference context implementation
58 using tcu::TextureFormat;
59 using tcu::PixelBufferAccess;
60 using tcu::ConstPixelBufferAccess;
62 // Utilities for ReferenceContext
65 #define RC_ERROR_RET(ERR, RET) \
69 } while (deGetFalse())
71 #define RC_IF_ERROR(COND, ERR, RET) \
74 RC_ERROR_RET(ERR, RET); \
75 } while (deGetFalse())
77 static inline tcu::PixelBufferAccess nullAccess (void)
79 return tcu::PixelBufferAccess(TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT8), 0, 0, 0, DE_NULL);
82 static inline bool isEmpty (const tcu::ConstPixelBufferAccess& access)
84 return access.getWidth() == 0 || access.getHeight() == 0 || access.getDepth() == 0;
87 static inline bool isEmpty (const rr::MultisampleConstPixelBufferAccess& access)
89 return access.raw().getWidth() == 0 || access.raw().getHeight() == 0 || access.raw().getDepth() == 0;
92 static inline bool isEmpty (const IVec4& rect)
94 return rect.z() == 0 || rect.w() == 0;
97 inline int getNumMipLevels1D (int size)
99 return deLog2Floor32(size)+1;
102 inline int getNumMipLevels2D (int width, int height)
104 return deLog2Floor32(de::max(width, height))+1;
107 inline int getNumMipLevels3D (int width, int height, int depth)
109 return deLog2Floor32(de::max(width, de::max(height, depth)))+1;
112 inline int getMipLevelSize (int baseLevelSize, int levelNdx)
114 return de::max(baseLevelSize >> levelNdx, 1);
117 inline bool isMipmapFilter (const tcu::Sampler::FilterMode mode)
119 return mode != tcu::Sampler::NEAREST && mode != tcu::Sampler::LINEAR;
122 static tcu::CubeFace texTargetToFace (Framebuffer::TexTarget target)
126 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X: return tcu::CUBEFACE_NEGATIVE_X;
127 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X: return tcu::CUBEFACE_POSITIVE_X;
128 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y: return tcu::CUBEFACE_NEGATIVE_Y;
129 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y: return tcu::CUBEFACE_POSITIVE_Y;
130 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z: return tcu::CUBEFACE_NEGATIVE_Z;
131 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z: return tcu::CUBEFACE_POSITIVE_Z;
132 default: return tcu::CUBEFACE_LAST;
136 static Framebuffer::TexTarget texLayeredTypeToTarget (Texture::Type type)
140 case Texture::TYPE_2D_ARRAY: return Framebuffer::TEXTARGET_2D_ARRAY;
141 case Texture::TYPE_3D: return Framebuffer::TEXTARGET_3D;
142 case Texture::TYPE_CUBE_MAP_ARRAY: return Framebuffer::TEXTARGET_CUBE_MAP_ARRAY;
143 default: return Framebuffer::TEXTARGET_LAST;
147 static tcu::CubeFace mapGLCubeFace (deUint32 face)
151 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return tcu::CUBEFACE_NEGATIVE_X;
152 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return tcu::CUBEFACE_POSITIVE_X;
153 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return tcu::CUBEFACE_NEGATIVE_Y;
154 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return tcu::CUBEFACE_POSITIVE_Y;
155 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return tcu::CUBEFACE_NEGATIVE_Z;
156 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return tcu::CUBEFACE_POSITIVE_Z;
157 default: return tcu::CUBEFACE_LAST;
161 tcu::TextureFormat toTextureFormat (const tcu::PixelFormat& pixelFmt)
165 tcu::PixelFormat pixelFmt;
166 tcu::TextureFormat texFmt;
169 { tcu::PixelFormat(8,8,8,8), tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) },
170 { tcu::PixelFormat(8,8,8,0), tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8) },
171 { tcu::PixelFormat(4,4,4,4), tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_SHORT_4444) },
172 { tcu::PixelFormat(5,5,5,1), tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_SHORT_5551) },
173 { tcu::PixelFormat(5,6,5,0), tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_SHORT_565) }
176 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pixelFormatMap); ndx++)
178 if (pixelFormatMap[ndx].pixelFmt == pixelFmt)
179 return pixelFormatMap[ndx].texFmt;
182 TCU_FAIL("Can't map pixel format to texture format");
185 tcu::TextureFormat toNonSRGBFormat (const tcu::TextureFormat& fmt)
189 case tcu::TextureFormat::sRGB:
190 return tcu::TextureFormat(tcu::TextureFormat::RGB, fmt.type);
191 case tcu::TextureFormat::sRGBA:
192 return tcu::TextureFormat(tcu::TextureFormat::RGBA, fmt.type);
198 tcu::TextureFormat getDepthFormat (int depthBits)
202 case 8: return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
203 case 16: return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
204 case 24: return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8);
205 case 32: return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
207 TCU_FAIL("Can't map depth buffer format");
211 tcu::TextureFormat getStencilFormat (int stencilBits)
215 case 8: return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
216 case 16: return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT16);
217 case 24: return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT_24_8);
218 case 32: return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32);
220 TCU_FAIL("Can't map depth buffer format");
224 static inline tcu::IVec4 intersect (const tcu::IVec4& a, const tcu::IVec4& b)
226 int x0 = de::max(a.x(), b.x());
227 int y0 = de::max(a.y(), b.y());
228 int x1 = de::min(a.x()+a.z(), b.x()+b.z());
229 int y1 = de::min(a.y()+a.w(), b.y()+b.w());
230 int w = de::max(0, x1-x0);
231 int h = de::max(0, y1-y0);
233 return tcu::IVec4(x0, y0, w, h);
236 static inline tcu::IVec4 getBufferRect (const rr::MultisampleConstPixelBufferAccess& access)
238 return tcu::IVec4(0, 0, access.raw().getHeight(), access.raw().getDepth());
241 ReferenceContextLimits::ReferenceContextLimits (const glu::RenderContext& renderCtx)
242 : contextType (renderCtx.getType())
243 , maxTextureImageUnits (0)
244 , maxTexture2DSize (0)
245 , maxTextureCubeSize (0)
246 , maxTexture2DArrayLayers (0)
247 , maxTexture3DSize (0)
248 , maxRenderbufferSize (0)
249 , maxVertexAttribs (0)
252 const glw::Functions& gl = renderCtx.getFunctions();
254 // When the OpenGL ES's major version bigger than 3, and the expect context version is 3,
255 // we need query the real GL context version and update the real version to reference context.
256 if (glu::IsES3Compatible(gl) && isES2Context(contextType))
258 int majorVersion = contextType.getMajorVersion();
259 int minorVersion = contextType.getMinorVersion();
260 gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
261 gl.getIntegerv(GL_MINOR_VERSION, &minorVersion);
262 contextType.setAPI(glu::ApiType::es(majorVersion, minorVersion));
265 gl.getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
266 gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexture2DSize);
267 gl.getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxTextureCubeSize);
268 gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxRenderbufferSize);
269 gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
270 gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
272 if (contextSupports(contextType, glu::ApiType::es(3,0)) || glu::isContextTypeGLCore(contextType))
274 gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTexture2DArrayLayers);
275 gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxTexture3DSize);
278 // Limit texture sizes to supported values
279 maxTexture2DSize = de::min(maxTexture2DSize, (int)MAX_TEXTURE_SIZE);
280 maxTextureCubeSize = de::min(maxTextureCubeSize, (int)MAX_TEXTURE_SIZE);
281 maxTexture3DSize = de::min(maxTexture3DSize, (int)MAX_TEXTURE_SIZE);
283 GLU_EXPECT_NO_ERROR(gl.getError(), GL_NO_ERROR);
285 // \todo [pyry] Figure out following things:
286 // + supported fbo configurations
289 // \todo [2013-08-01 pyry] Do we want to make these conditional based on renderCtx?
290 addExtension("GL_EXT_color_buffer_half_float");
291 addExtension("GL_EXT_color_buffer_float");
293 if (contextSupports(contextType, glu::ApiType::es(3,1)))
294 addExtension("GL_EXT_texture_cube_map_array");
297 void ReferenceContextLimits::addExtension (const char* extension)
299 extensionList.push_back(extension);
301 if (!extensionStr.empty())
303 extensionStr += extension;
306 ReferenceContextBuffers::ReferenceContextBuffers (const tcu::PixelFormat& colorBits, int depthBits, int stencilBits, int width, int height, int samples)
308 m_colorbuffer.setStorage(toTextureFormat(colorBits), samples, width, height);
311 m_depthbuffer.setStorage(getDepthFormat(depthBits), samples, width, height);
314 m_stencilbuffer.setStorage(getStencilFormat(stencilBits), samples, width, height);
317 ReferenceContext::StencilState::StencilState (void)
321 , opStencilFail (GL_KEEP)
322 , opDepthFail (GL_KEEP)
323 , opDepthPass (GL_KEEP)
328 ReferenceContext::ReferenceContext (const ReferenceContextLimits& limits, const rr::MultisamplePixelBufferAccess& colorbuffer, const rr::MultisamplePixelBufferAccess& depthbuffer, const rr::MultisamplePixelBufferAccess& stencilbuffer)
329 : Context (limits.contextType)
331 , m_defaultColorbuffer (colorbuffer)
332 , m_defaultDepthbuffer (depthbuffer)
333 , m_defaultStencilbuffer (stencilbuffer)
334 , m_clientVertexArray (0, m_limits.maxVertexAttribs)
336 , m_viewport (0, 0, colorbuffer.raw().getHeight(), colorbuffer.raw().getDepth())
338 , m_activeTexture (0)
339 , m_textureUnits (m_limits.maxTextureImageUnits)
341 , m_emptyTex2D (isES2Context(limits.contextType))
342 , m_emptyTexCube (!isES2Context(limits.contextType))
343 , m_emptyTex2DArray ()
345 , m_emptyTexCubeArray ()
347 , m_pixelUnpackRowLength (0)
348 , m_pixelUnpackSkipRows (0)
349 , m_pixelUnpackSkipPixels (0)
350 , m_pixelUnpackImageHeight (0)
351 , m_pixelUnpackSkipImages (0)
352 , m_pixelUnpackAlignment (4)
353 , m_pixelPackAlignment (4)
355 , m_readFramebufferBinding (DE_NULL)
356 , m_drawFramebufferBinding (DE_NULL)
357 , m_renderbufferBinding (DE_NULL)
358 , m_vertexArrayBinding (DE_NULL)
359 , m_currentProgram (DE_NULL)
361 , m_arrayBufferBinding (DE_NULL)
362 , m_pixelPackBufferBinding (DE_NULL)
363 , m_pixelUnpackBufferBinding (DE_NULL)
364 , m_transformFeedbackBufferBinding (DE_NULL)
365 , m_uniformBufferBinding (DE_NULL)
366 , m_copyReadBufferBinding (DE_NULL)
367 , m_copyWriteBufferBinding (DE_NULL)
368 , m_drawIndirectBufferBinding (DE_NULL)
370 , m_clearColor (0.0f, 0.0f, 0.0f, 0.0f)
371 , m_clearDepth (1.0f)
373 , m_scissorEnabled (false)
374 , m_scissorBox (m_viewport)
375 , m_stencilTestEnabled (false)
376 , m_depthTestEnabled (false)
377 , m_depthFunc (GL_LESS)
378 , m_depthRangeNear (0.0f)
379 , m_depthRangeFar (1.0f)
380 , m_polygonOffsetFactor (0.0f)
381 , m_polygonOffsetUnits (0.0f)
382 , m_polygonOffsetFillEnabled (false)
383 , m_provokingFirstVertexConvention (false)
384 , m_blendEnabled (false)
385 , m_blendModeRGB (GL_FUNC_ADD)
386 , m_blendModeAlpha (GL_FUNC_ADD)
387 , m_blendFactorSrcRGB (GL_ONE)
388 , m_blendFactorDstRGB (GL_ZERO)
389 , m_blendFactorSrcAlpha (GL_ONE)
390 , m_blendFactorDstAlpha (GL_ZERO)
391 , m_blendColor (0.0f, 0.0f, 0.0f, 0.0f)
392 , m_sRGBUpdateEnabled (true)
393 , m_depthClampEnabled (false)
394 , m_colorMask (true, true, true, true)
396 , m_currentAttribs (m_limits.maxVertexAttribs, rr::GenericVec4(tcu::Vec4(0, 0, 0, 1)))
398 , m_primitiveRestartFixedIndex (false)
399 , m_primitiveRestartSettableIndex (false)
400 , m_primitiveRestartIndex (0)
402 , m_lastError (GL_NO_ERROR)
404 // Create empty textures to be used when texture objects are incomplete.
405 m_emptyTex1D.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
406 m_emptyTex1D.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
407 m_emptyTex1D.getSampler().minFilter = tcu::Sampler::NEAREST;
408 m_emptyTex1D.getSampler().magFilter = tcu::Sampler::NEAREST;
409 m_emptyTex1D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1);
410 m_emptyTex1D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
411 m_emptyTex1D.updateView(tcu::Sampler::MODE_LAST);
413 m_emptyTex2D.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
414 m_emptyTex2D.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
415 m_emptyTex2D.getSampler().minFilter = tcu::Sampler::NEAREST;
416 m_emptyTex2D.getSampler().magFilter = tcu::Sampler::NEAREST;
417 m_emptyTex2D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
418 m_emptyTex2D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
419 m_emptyTex2D.updateView(tcu::Sampler::MODE_LAST);
421 m_emptyTexCube.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
422 m_emptyTexCube.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
423 m_emptyTexCube.getSampler().minFilter = tcu::Sampler::NEAREST;
424 m_emptyTexCube.getSampler().magFilter = tcu::Sampler::NEAREST;
425 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
427 m_emptyTexCube.allocFace(0, (tcu::CubeFace)face, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
428 m_emptyTexCube.getFace(0, (tcu::CubeFace)face).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
430 m_emptyTexCube.updateView(tcu::Sampler::MODE_LAST);
432 m_emptyTex2DArray.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
433 m_emptyTex2DArray.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
434 m_emptyTex2DArray.getSampler().minFilter = tcu::Sampler::NEAREST;
435 m_emptyTex2DArray.getSampler().magFilter = tcu::Sampler::NEAREST;
436 m_emptyTex2DArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
437 m_emptyTex2DArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
438 m_emptyTex2DArray.updateView(tcu::Sampler::MODE_LAST);
440 m_emptyTex3D.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
441 m_emptyTex3D.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
442 m_emptyTex3D.getSampler().wrapR = tcu::Sampler::CLAMP_TO_EDGE;
443 m_emptyTex3D.getSampler().minFilter = tcu::Sampler::NEAREST;
444 m_emptyTex3D.getSampler().magFilter = tcu::Sampler::NEAREST;
445 m_emptyTex3D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
446 m_emptyTex3D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
447 m_emptyTex3D.updateView(tcu::Sampler::MODE_LAST);
449 m_emptyTexCubeArray.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
450 m_emptyTexCubeArray.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
451 m_emptyTexCubeArray.getSampler().minFilter = tcu::Sampler::NEAREST;
452 m_emptyTexCubeArray.getSampler().magFilter = tcu::Sampler::NEAREST;
453 m_emptyTexCubeArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 6);
454 for (int faceNdx = 0; faceNdx < 6; faceNdx++)
455 m_emptyTexCubeArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, faceNdx);
456 m_emptyTexCubeArray.updateView(tcu::Sampler::MODE_LAST);
458 for (int unitNdx = 0; unitNdx < m_limits.maxTextureImageUnits; unitNdx++)
459 m_textureUnits[unitNdx].defaultCubeTex.getSampler().seamlessCubeMap = !isES2Context(limits.contextType);
461 if (glu::isContextTypeGLCore(getType()))
462 m_sRGBUpdateEnabled = false;
465 ReferenceContext::~ReferenceContext (void)
467 // Destroy all objects -- verifies that ref counting works
469 vector<VertexArray*> vertexArrays;
470 m_vertexArrays.getAll(vertexArrays);
471 for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
472 deleteVertexArray(*i);
474 DE_ASSERT(m_clientVertexArray.getRefCount() == 1);
478 vector<Texture*> textures;
479 m_textures.getAll(textures);
480 for (vector<Texture*>::iterator i = textures.begin(); i != textures.end(); i++)
485 vector<Framebuffer*> framebuffers;
486 m_framebuffers.getAll(framebuffers);
487 for (vector<Framebuffer*>::iterator i = framebuffers.begin(); i != framebuffers.end(); i++)
488 deleteFramebuffer(*i);
492 vector<Renderbuffer*> renderbuffers;
493 m_renderbuffers.getAll(renderbuffers);
494 for (vector<Renderbuffer*>::iterator i = renderbuffers.begin(); i != renderbuffers.end(); i++)
495 deleteRenderbuffer(*i);
499 vector<DataBuffer*> buffers;
500 m_buffers.getAll(buffers);
501 for (vector<DataBuffer*>::iterator i = buffers.begin(); i != buffers.end(); i++)
506 vector<ShaderProgramObjectContainer*> programs;
507 m_programs.getAll(programs);
508 for (vector<ShaderProgramObjectContainer*>::iterator i = programs.begin(); i != programs.end(); i++)
509 deleteProgramObject(*i);
513 void ReferenceContext::activeTexture (deUint32 texture)
515 if (deInBounds32(texture, GL_TEXTURE0, GL_TEXTURE0 + (deUint32)m_textureUnits.size()))
516 m_activeTexture = texture - GL_TEXTURE0;
518 setError(GL_INVALID_ENUM);
521 void ReferenceContext::setTex1DBinding (int unitNdx, Texture1D* texture)
523 if (m_textureUnits[unitNdx].tex1DBinding)
525 m_textures.releaseReference(m_textureUnits[unitNdx].tex1DBinding);
526 m_textureUnits[unitNdx].tex1DBinding = DE_NULL;
531 m_textures.acquireReference(texture);
532 m_textureUnits[unitNdx].tex1DBinding = texture;
536 void ReferenceContext::setTex2DBinding (int unitNdx, Texture2D* texture)
538 if (m_textureUnits[unitNdx].tex2DBinding)
540 m_textures.releaseReference(m_textureUnits[unitNdx].tex2DBinding);
541 m_textureUnits[unitNdx].tex2DBinding = DE_NULL;
546 m_textures.acquireReference(texture);
547 m_textureUnits[unitNdx].tex2DBinding = texture;
551 void ReferenceContext::setTexCubeBinding (int unitNdx, TextureCube* texture)
553 if (m_textureUnits[unitNdx].texCubeBinding)
555 m_textures.releaseReference(m_textureUnits[unitNdx].texCubeBinding);
556 m_textureUnits[unitNdx].texCubeBinding = DE_NULL;
561 m_textures.acquireReference(texture);
562 m_textureUnits[unitNdx].texCubeBinding = texture;
566 void ReferenceContext::setTex2DArrayBinding (int unitNdx, Texture2DArray* texture)
568 if (m_textureUnits[unitNdx].tex2DArrayBinding)
570 m_textures.releaseReference(m_textureUnits[unitNdx].tex2DArrayBinding);
571 m_textureUnits[unitNdx].tex2DArrayBinding = DE_NULL;
576 m_textures.acquireReference(texture);
577 m_textureUnits[unitNdx].tex2DArrayBinding = texture;
581 void ReferenceContext::setTex3DBinding (int unitNdx, Texture3D* texture)
583 if (m_textureUnits[unitNdx].tex3DBinding)
585 m_textures.releaseReference(m_textureUnits[unitNdx].tex3DBinding);
586 m_textureUnits[unitNdx].tex3DBinding = DE_NULL;
591 m_textures.acquireReference(texture);
592 m_textureUnits[unitNdx].tex3DBinding = texture;
596 void ReferenceContext::setTexCubeArrayBinding (int unitNdx, TextureCubeArray* texture)
598 if (m_textureUnits[unitNdx].texCubeArrayBinding)
600 m_textures.releaseReference(m_textureUnits[unitNdx].texCubeArrayBinding);
601 m_textureUnits[unitNdx].texCubeArrayBinding = DE_NULL;
606 m_textures.acquireReference(texture);
607 m_textureUnits[unitNdx].texCubeArrayBinding = texture;
611 void ReferenceContext::bindTexture (deUint32 target, deUint32 texture)
613 int unitNdx = m_activeTexture;
615 RC_IF_ERROR(target != GL_TEXTURE_1D &&
616 target != GL_TEXTURE_2D &&
617 target != GL_TEXTURE_CUBE_MAP &&
618 target != GL_TEXTURE_2D_ARRAY &&
619 target != GL_TEXTURE_3D &&
620 target != GL_TEXTURE_CUBE_MAP_ARRAY,
621 GL_INVALID_ENUM, RC_RET_VOID);
623 RC_IF_ERROR(glu::isContextTypeES(m_limits.contextType) && (target == GL_TEXTURE_1D), GL_INVALID_ENUM, RC_RET_VOID);
630 case GL_TEXTURE_1D: setTex1DBinding (unitNdx, DE_NULL); break;
631 case GL_TEXTURE_2D: setTex2DBinding (unitNdx, DE_NULL); break;
632 case GL_TEXTURE_CUBE_MAP: setTexCubeBinding (unitNdx, DE_NULL); break;
633 case GL_TEXTURE_2D_ARRAY: setTex2DArrayBinding (unitNdx, DE_NULL); break;
634 case GL_TEXTURE_3D: setTex3DBinding (unitNdx, DE_NULL); break;
635 case GL_TEXTURE_CUBE_MAP_ARRAY: setTexCubeArrayBinding (unitNdx, DE_NULL); break;
642 Texture* texObj = m_textures.find(texture);
647 Texture::Type expectedType = Texture::TYPE_LAST;
650 case GL_TEXTURE_1D: expectedType = Texture::TYPE_1D; break;
651 case GL_TEXTURE_2D: expectedType = Texture::TYPE_2D; break;
652 case GL_TEXTURE_CUBE_MAP: expectedType = Texture::TYPE_CUBE_MAP; break;
653 case GL_TEXTURE_2D_ARRAY: expectedType = Texture::TYPE_2D_ARRAY; break;
654 case GL_TEXTURE_3D: expectedType = Texture::TYPE_3D; break;
655 case GL_TEXTURE_CUBE_MAP_ARRAY: expectedType = Texture::TYPE_CUBE_MAP_ARRAY; break;
659 RC_IF_ERROR(texObj->getType() != expectedType, GL_INVALID_OPERATION, RC_RET_VOID);
663 // New texture object.
664 bool seamlessCubeMap = !isES2Context(m_limits.contextType);
667 case GL_TEXTURE_1D: texObj = new Texture1D (texture); break;
668 case GL_TEXTURE_2D: texObj = new Texture2D (texture); break;
669 case GL_TEXTURE_CUBE_MAP: texObj = new TextureCube (texture, seamlessCubeMap); break;
670 case GL_TEXTURE_2D_ARRAY: texObj = new Texture2DArray (texture); break;
671 case GL_TEXTURE_3D: texObj = new Texture3D (texture); break;
672 case GL_TEXTURE_CUBE_MAP_ARRAY: texObj = new TextureCubeArray (texture); break;
677 m_textures.insert(texObj);
682 case GL_TEXTURE_1D: setTex1DBinding (unitNdx, static_cast<Texture1D*> (texObj)); break;
683 case GL_TEXTURE_2D: setTex2DBinding (unitNdx, static_cast<Texture2D*> (texObj)); break;
684 case GL_TEXTURE_CUBE_MAP: setTexCubeBinding (unitNdx, static_cast<TextureCube*> (texObj)); break;
685 case GL_TEXTURE_2D_ARRAY: setTex2DArrayBinding (unitNdx, static_cast<Texture2DArray*> (texObj)); break;
686 case GL_TEXTURE_3D: setTex3DBinding (unitNdx, static_cast<Texture3D*> (texObj)); break;
687 case GL_TEXTURE_CUBE_MAP_ARRAY: setTexCubeArrayBinding (unitNdx, static_cast<TextureCubeArray*> (texObj)); break;
694 void ReferenceContext::genTextures (int numTextures, deUint32* textures)
696 while (numTextures--)
697 *textures++ = m_textures.allocateName();
700 void ReferenceContext::deleteTextures (int numTextures, const deUint32* textures)
702 for (int i = 0; i < numTextures; i++)
704 deUint32 name = textures[i];
705 Texture* texture = name ? m_textures.find(name) : DE_NULL;
708 deleteTexture(texture);
712 void ReferenceContext::deleteTexture (Texture* texture)
714 // Unbind from context
715 for (int unitNdx = 0; unitNdx < (int)m_textureUnits.size(); unitNdx++)
717 if (m_textureUnits[unitNdx].tex1DBinding == texture) setTex1DBinding (unitNdx, DE_NULL);
718 else if (m_textureUnits[unitNdx].tex2DBinding == texture) setTex2DBinding (unitNdx, DE_NULL);
719 else if (m_textureUnits[unitNdx].texCubeBinding == texture) setTexCubeBinding (unitNdx, DE_NULL);
720 else if (m_textureUnits[unitNdx].tex2DArrayBinding == texture) setTex2DArrayBinding (unitNdx, DE_NULL);
721 else if (m_textureUnits[unitNdx].tex3DBinding == texture) setTex3DBinding (unitNdx, DE_NULL);
722 else if (m_textureUnits[unitNdx].texCubeArrayBinding == texture) setTexCubeArrayBinding (unitNdx, DE_NULL);
725 // Unbind from currently bound framebuffers
726 for (int ndx = 0; ndx < 2; ndx++)
728 rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
729 if (framebufferBinding)
731 int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
732 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
734 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
736 Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
737 if (attachment.name == texture->getName())
739 for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
740 releaseFboAttachmentReference(attachment);
741 attachment = Framebuffer::Attachment();
747 DE_ASSERT(texture->getRefCount() == 1);
748 m_textures.releaseReference(texture);
751 void ReferenceContext::bindFramebuffer (deUint32 target, deUint32 name)
753 Framebuffer* fbo = DE_NULL;
755 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
756 target != GL_DRAW_FRAMEBUFFER &&
757 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
761 // Find or create framebuffer object.
762 fbo = m_framebuffers.find(name);
765 fbo = new Framebuffer(name);
766 m_framebuffers.insert(fbo);
770 for (int ndx = 0; ndx < 2; ndx++)
772 deUint32 bindingTarget = ndx ? GL_DRAW_FRAMEBUFFER : GL_READ_FRAMEBUFFER;
773 rc::Framebuffer*& binding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
775 if (target != GL_FRAMEBUFFER && target != bindingTarget)
776 continue; // Doesn't match this target.
778 // Remove old references
781 // Clear all attachment point references
782 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
783 releaseFboAttachmentReference(binding->getAttachment((Framebuffer::AttachmentPoint)point));
785 m_framebuffers.releaseReference(binding);
788 // Create new references
791 m_framebuffers.acquireReference(fbo);
793 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
794 acquireFboAttachmentReference(fbo->getAttachment((Framebuffer::AttachmentPoint)point));
801 void ReferenceContext::genFramebuffers (int numFramebuffers, deUint32* framebuffers)
803 while (numFramebuffers--)
804 *framebuffers++ = m_framebuffers.allocateName();
807 void ReferenceContext::deleteFramebuffer (Framebuffer* framebuffer)
810 if (m_drawFramebufferBinding == framebuffer) bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
811 if (m_readFramebufferBinding == framebuffer) bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
813 DE_ASSERT(framebuffer->getRefCount() == 1);
814 m_framebuffers.releaseReference(framebuffer);
817 void ReferenceContext::deleteFramebuffers (int numFramebuffers, const deUint32* framebuffers)
819 for (int i = 0; i < numFramebuffers; i++)
821 deUint32 name = framebuffers[i];
822 Framebuffer* framebuffer = name ? m_framebuffers.find(name) : DE_NULL;
825 deleteFramebuffer(framebuffer);
829 void ReferenceContext::bindRenderbuffer (deUint32 target, deUint32 name)
831 Renderbuffer* rbo = DE_NULL;
833 RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
837 rbo = m_renderbuffers.find(name);
840 rbo = new Renderbuffer(name);
841 m_renderbuffers.insert(rbo);
845 // Remove old reference
846 if (m_renderbufferBinding)
847 m_renderbuffers.releaseReference(m_renderbufferBinding);
849 // Create new reference
851 m_renderbuffers.acquireReference(rbo);
853 m_renderbufferBinding = rbo;
856 void ReferenceContext::genRenderbuffers (int numRenderbuffers, deUint32* renderbuffers)
858 while (numRenderbuffers--)
859 *renderbuffers++ = m_renderbuffers.allocateName();
862 void ReferenceContext::deleteRenderbuffer (Renderbuffer* renderbuffer)
864 if (m_renderbufferBinding == renderbuffer)
865 bindRenderbuffer(GL_RENDERBUFFER, 0);
867 // Unbind from currently bound framebuffers
868 for (int ndx = 0; ndx < 2; ndx++)
870 rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
871 if (framebufferBinding)
873 int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
874 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
876 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
878 Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
879 if (attachment.name == renderbuffer->getName())
881 for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
882 releaseFboAttachmentReference(attachment);
883 attachment = Framebuffer::Attachment();
889 DE_ASSERT(renderbuffer->getRefCount() == 1);
890 m_renderbuffers.releaseReference(renderbuffer);
893 void ReferenceContext::deleteRenderbuffers (int numRenderbuffers, const deUint32* renderbuffers)
895 for (int i = 0; i < numRenderbuffers; i++)
897 deUint32 name = renderbuffers[i];
898 Renderbuffer* renderbuffer = name ? m_renderbuffers.find(name) : DE_NULL;
901 deleteRenderbuffer(renderbuffer);
905 void ReferenceContext::pixelStorei (deUint32 pname, int param)
909 case GL_UNPACK_ALIGNMENT:
910 RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
911 m_pixelUnpackAlignment = param;
914 case GL_PACK_ALIGNMENT:
915 RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
916 m_pixelPackAlignment = param;
919 case GL_UNPACK_ROW_LENGTH:
920 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
921 m_pixelUnpackRowLength = param;
924 case GL_UNPACK_SKIP_ROWS:
925 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
926 m_pixelUnpackSkipRows = param;
929 case GL_UNPACK_SKIP_PIXELS:
930 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
931 m_pixelUnpackSkipPixels = param;
934 case GL_UNPACK_IMAGE_HEIGHT:
935 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
936 m_pixelUnpackImageHeight = param;
939 case GL_UNPACK_SKIP_IMAGES:
940 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
941 m_pixelUnpackSkipImages = param;
945 setError(GL_INVALID_ENUM);
949 tcu::ConstPixelBufferAccess ReferenceContext::getUnpack2DAccess (const tcu::TextureFormat& format, int width, int height, const void* data)
951 int pixelSize = format.getPixelSize();
952 int rowLen = m_pixelUnpackRowLength > 0 ? m_pixelUnpackRowLength : width;
953 int rowPitch = deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
954 const deUint8* ptr = (const deUint8*)data + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;
956 return tcu::ConstPixelBufferAccess(format, width, height, 1, rowPitch, 0, ptr);
959 tcu::ConstPixelBufferAccess ReferenceContext::getUnpack3DAccess (const tcu::TextureFormat& format, int width, int height, int depth, const void* data)
961 int pixelSize = format.getPixelSize();
962 int rowLen = m_pixelUnpackRowLength > 0 ? m_pixelUnpackRowLength : width;
963 int imageHeight = m_pixelUnpackImageHeight > 0 ? m_pixelUnpackImageHeight : height;
964 int rowPitch = deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
965 int slicePitch = imageHeight*rowPitch;
966 const deUint8* ptr = (const deUint8*)data + m_pixelUnpackSkipImages*slicePitch + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;
968 return tcu::ConstPixelBufferAccess(format, width, height, depth, rowPitch, slicePitch, ptr);
971 static tcu::TextureFormat mapInternalFormat (deUint32 internalFormat)
973 switch (internalFormat)
975 case GL_ALPHA: return TextureFormat(TextureFormat::A, TextureFormat::UNORM_INT8);
976 case GL_LUMINANCE: return TextureFormat(TextureFormat::L, TextureFormat::UNORM_INT8);
977 case GL_LUMINANCE_ALPHA: return TextureFormat(TextureFormat::LA, TextureFormat::UNORM_INT8);
978 case GL_RGB: return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8);
979 case GL_RGBA: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
982 return glu::mapGLInternalFormat(internalFormat);
986 static void depthValueFloatClampCopy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src)
988 int width = dst.getWidth();
989 int height = dst.getHeight();
990 int depth = dst.getDepth();
992 DE_ASSERT(src.getWidth() == width && src.getHeight() == height && src.getDepth() == depth);
996 if (src.getFormat().order == tcu::TextureFormat::DS && dst.getFormat().order == tcu::TextureFormat::DS)
998 // copy only depth and stencil
999 for (int z = 0; z < depth; z++)
1000 for (int y = 0; y < height; y++)
1001 for (int x = 0; x < width; x++)
1003 dst.setPixDepth(de::clamp(src.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
1004 dst.setPixStencil(src.getPixStencil(x, y, z), x, y, z);
1010 for (int z = 0; z < depth; z++)
1011 for (int y = 0; y < height; y++)
1012 for (int x = 0; x < width; x++)
1013 dst.setPixDepth(de::clamp(src.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
1017 void ReferenceContext::texImage1D (deUint32 target, int level, deUint32 internalFormat, int width, int border, deUint32 format, deUint32 type, const void* data)
1019 texImage2D(target, level, internalFormat, width, 1, border, format, type, data);
1022 void ReferenceContext::texImage2D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int border, deUint32 format, deUint32 type, const void* data)
1024 texImage3D(target, level, internalFormat, width, height, 1, border, format, type, data);
1027 static void clearToTextureInitialValue (PixelBufferAccess access)
1029 const bool hasDepth = access.getFormat().order == tcu::TextureFormat::D || access.getFormat().order == tcu::TextureFormat::DS;
1030 const bool hasStencil = access.getFormat().order == tcu::TextureFormat::S || access.getFormat().order == tcu::TextureFormat::DS;
1031 const bool hasColor = !hasDepth && !hasStencil;
1034 tcu::clearDepth(access, 0.0f);
1036 tcu::clearStencil(access, 0u);
1038 tcu::clear(access, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1041 void ReferenceContext::texImage3D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int depth, int border, deUint32 format, deUint32 type, const void* data)
1043 TextureUnit& unit = m_textureUnits[m_activeTexture];
1044 const void* unpackPtr = getPixelUnpackPtr(data);
1045 const bool isDstFloatDepthFormat = (internalFormat == GL_DEPTH_COMPONENT32F || internalFormat == GL_DEPTH32F_STENCIL8); // depth components are limited to [0,1] range
1046 TextureFormat storageFmt;
1047 TextureFormat transferFmt;
1049 RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1050 RC_IF_ERROR(width < 0 || height < 0 || depth < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1052 // Map storage format.
1053 storageFmt = mapInternalFormat(internalFormat);
1054 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1055 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1057 // Map transfer format.
1058 transferFmt = glu::mapGLTransferFormat(format, type);
1059 RC_IF_ERROR(transferFmt.order == TextureFormat::CHANNELORDER_LAST ||
1060 transferFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1062 if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
1064 // Validate size and level.
1065 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height != 1 || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1066 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1068 Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;
1070 if (texture->isImmutable())
1072 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1074 ConstPixelBufferAccess dst(texture->getLevel(level));
1075 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1076 width != dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
1079 texture->allocLevel(level, storageFmt, width);
1083 ConstPixelBufferAccess src = getUnpack2DAccess(transferFmt, width, 1, unpackPtr);
1084 PixelBufferAccess dst (texture->getLevel(level));
1086 if (isDstFloatDepthFormat)
1087 depthValueFloatClampCopy(dst, src);
1089 tcu::copy(dst, src);
1093 // No data supplied, clear to initial
1094 clearToTextureInitialValue(texture->getLevel(level));
1097 else if (target == GL_TEXTURE_2D)
1099 // Validate size and level.
1100 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1101 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1103 Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;
1105 if (texture->isImmutable())
1107 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1109 ConstPixelBufferAccess dst(texture->getLevel(level));
1110 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1111 width != dst.getWidth() ||
1112 height != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1115 texture->allocLevel(level, storageFmt, width, height);
1119 ConstPixelBufferAccess src = getUnpack2DAccess(transferFmt, width, height, unpackPtr);
1120 PixelBufferAccess dst (texture->getLevel(level));
1122 if (isDstFloatDepthFormat)
1123 depthValueFloatClampCopy(dst, src);
1125 tcu::copy(dst, src);
1129 // No data supplied, clear to initial
1130 clearToTextureInitialValue(texture->getLevel(level));
1133 else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1134 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1135 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1136 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1137 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1138 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1140 // Validate size and level.
1141 RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1142 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);
1144 TextureCube* texture = unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
1145 tcu::CubeFace face = mapGLCubeFace(target);
1147 if (texture->isImmutable())
1149 RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);
1151 ConstPixelBufferAccess dst(texture->getFace(level, face));
1152 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1153 width != dst.getWidth() ||
1154 height != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1157 texture->allocFace(level, face, storageFmt, width, height);
1161 ConstPixelBufferAccess src = getUnpack2DAccess(transferFmt, width, height, unpackPtr);
1162 PixelBufferAccess dst (texture->getFace(level, face));
1164 if (isDstFloatDepthFormat)
1165 depthValueFloatClampCopy(dst, src);
1167 tcu::copy(dst, src);
1171 // No data supplied, clear to initial
1172 clearToTextureInitialValue(texture->getFace(level, face));
1175 else if (target == GL_TEXTURE_2D_ARRAY)
1177 // Validate size and level.
1178 RC_IF_ERROR(width > m_limits.maxTexture2DSize ||
1179 height > m_limits.maxTexture2DSize ||
1180 depth > m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1181 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1183 Texture2DArray* texture = unit.tex2DArrayBinding ? unit.tex2DArrayBinding : &unit.default2DArrayTex;
1185 if (texture->isImmutable())
1187 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1189 ConstPixelBufferAccess dst(texture->getLevel(level));
1190 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1191 width != dst.getWidth() ||
1192 height != dst.getHeight() ||
1193 depth != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1196 texture->allocLevel(level, storageFmt, width, height, depth);
1200 ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1201 PixelBufferAccess dst (texture->getLevel(level));
1203 if (isDstFloatDepthFormat)
1204 depthValueFloatClampCopy(dst, src);
1206 tcu::copy(dst, src);
1210 // No data supplied, clear to initial
1211 clearToTextureInitialValue(texture->getLevel(level));
1214 else if (target == GL_TEXTURE_3D)
1216 // Validate size and level.
1217 RC_IF_ERROR(width > m_limits.maxTexture3DSize ||
1218 height > m_limits.maxTexture3DSize ||
1219 depth > m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
1220 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture3DSize), GL_INVALID_VALUE, RC_RET_VOID);
1222 Texture3D* texture = unit.tex3DBinding ? unit.tex3DBinding : &unit.default3DTex;
1224 if (texture->isImmutable())
1226 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1228 ConstPixelBufferAccess dst(texture->getLevel(level));
1229 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1230 width != dst.getWidth() ||
1231 height != dst.getHeight() ||
1232 depth != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1235 texture->allocLevel(level, storageFmt, width, height, depth);
1239 ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1240 PixelBufferAccess dst (texture->getLevel(level));
1242 if (isDstFloatDepthFormat)
1243 depthValueFloatClampCopy(dst, src);
1245 tcu::copy(dst, src);
1249 // No data supplied, clear to initial
1250 clearToTextureInitialValue(texture->getLevel(level));
1253 else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1255 // Validate size and level.
1256 RC_IF_ERROR(width != height ||
1257 width > m_limits.maxTexture2DSize ||
1259 depth > m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1260 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1262 TextureCubeArray* texture = unit.texCubeArrayBinding ? unit.texCubeArrayBinding : &unit.defaultCubeArrayTex;
1264 if (texture->isImmutable())
1266 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1268 ConstPixelBufferAccess dst(texture->getLevel(level));
1269 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1270 width != dst.getWidth() ||
1271 height != dst.getHeight() ||
1272 depth != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1275 texture->allocLevel(level, storageFmt, width, height, depth);
1279 ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1280 PixelBufferAccess dst (texture->getLevel(level));
1282 if (isDstFloatDepthFormat)
1283 depthValueFloatClampCopy(dst, src);
1285 tcu::copy(dst, src);
1289 // No data supplied, clear to initial
1290 clearToTextureInitialValue(texture->getLevel(level));
1294 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1297 void ReferenceContext::texSubImage1D (deUint32 target, int level, int xoffset, int width, deUint32 format, deUint32 type, const void* data)
1299 texSubImage2D(target, level, xoffset, 0, width, 1, format, type, data);
1302 void ReferenceContext::texSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int width, int height, deUint32 format, deUint32 type, const void* data)
1304 texSubImage3D(target, level, xoffset, yoffset, 0, width, height, 1, format, type, data);
1307 void ReferenceContext::texSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, deUint32 format, deUint32 type, const void* data)
1309 TextureUnit& unit = m_textureUnits[m_activeTexture];
1311 RC_IF_ERROR(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE, RC_RET_VOID);
1312 RC_IF_ERROR(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE, RC_RET_VOID);
1314 TextureFormat transferFmt = glu::mapGLTransferFormat(format, type);
1315 RC_IF_ERROR(transferFmt.order == TextureFormat::CHANNELORDER_LAST ||
1316 transferFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1318 ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, getPixelUnpackPtr(data));
1320 if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
1322 Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;
1324 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1326 PixelBufferAccess dst = texture.getLevel(level);
1328 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1329 yoffset + height > dst.getHeight() ||
1330 zoffset + depth > dst.getDepth(),
1331 GL_INVALID_VALUE, RC_RET_VOID);
1333 // depth components are limited to [0,1] range
1334 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1335 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1337 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1339 else if (target == GL_TEXTURE_2D)
1341 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1343 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1345 PixelBufferAccess dst = texture.getLevel(level);
1347 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1348 yoffset + height > dst.getHeight() ||
1349 zoffset + depth > dst.getDepth(),
1350 GL_INVALID_VALUE, RC_RET_VOID);
1352 // depth components are limited to [0,1] range
1353 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1354 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1356 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1358 else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1359 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1360 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1361 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1362 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1363 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1365 TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1366 tcu::CubeFace face = mapGLCubeFace(target);
1368 RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);
1370 PixelBufferAccess dst = texture.getFace(level, face);
1372 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1373 yoffset + height > dst.getHeight() ||
1374 zoffset + depth > dst.getDepth(),
1375 GL_INVALID_VALUE, RC_RET_VOID);
1377 // depth components are limited to [0,1] range
1378 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1379 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1381 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1383 else if (target == GL_TEXTURE_3D)
1385 Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;
1387 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1389 PixelBufferAccess dst = texture.getLevel(level);
1391 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1392 yoffset + height > dst.getHeight() ||
1393 zoffset + depth > dst.getDepth(),
1394 GL_INVALID_VALUE, RC_RET_VOID);
1396 // depth components are limited to [0,1] range
1397 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1398 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1400 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1402 else if (target == GL_TEXTURE_2D_ARRAY)
1404 Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;
1406 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1408 PixelBufferAccess dst = texture.getLevel(level);
1410 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1411 yoffset + height > dst.getHeight() ||
1412 zoffset + depth > dst.getDepth(),
1413 GL_INVALID_VALUE, RC_RET_VOID);
1415 // depth components are limited to [0,1] range
1416 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1417 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1419 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1421 else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1423 TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;
1425 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1427 PixelBufferAccess dst = texture.getLevel(level);
1429 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1430 yoffset + height > dst.getHeight() ||
1431 zoffset + depth > dst.getDepth(),
1432 GL_INVALID_VALUE, RC_RET_VOID);
1434 // depth components are limited to [0,1] range
1435 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1436 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1438 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1441 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1444 void ReferenceContext::copyTexImage1D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int border)
1446 TextureUnit& unit = m_textureUnits[m_activeTexture];
1447 TextureFormat storageFmt;
1448 rr::MultisampleConstPixelBufferAccess src = getReadColorbuffer();
1450 RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1451 RC_IF_ERROR(width < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1452 RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1454 // Map storage format.
1455 storageFmt = mapInternalFormat(internalFormat);
1456 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1457 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1459 if (target == GL_TEXTURE_1D)
1461 // Validate size and level.
1462 RC_IF_ERROR(width > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1463 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1465 Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;
1467 if (texture->isImmutable())
1469 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1471 ConstPixelBufferAccess dst(texture->getLevel(level));
1472 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1473 width != dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
1476 texture->allocLevel(level, storageFmt, width);
1478 // Copy from current framebuffer.
1479 PixelBufferAccess dst = texture->getLevel(level);
1480 for (int xo = 0; xo < width; xo++)
1482 if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
1483 continue; // Undefined pixel.
1485 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo, 0);
1489 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1492 void ReferenceContext::copyTexImage2D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int height, int border)
1494 TextureUnit& unit = m_textureUnits[m_activeTexture];
1495 TextureFormat storageFmt;
1496 rr::MultisampleConstPixelBufferAccess src = getReadColorbuffer();
1498 RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1499 RC_IF_ERROR(width < 0 || height < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1500 RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1502 // Map storage format.
1503 storageFmt = mapInternalFormat(internalFormat);
1504 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1505 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1507 if (target == GL_TEXTURE_2D)
1509 // Validate size and level.
1510 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1511 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1513 Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;
1515 if (texture->isImmutable())
1517 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1519 ConstPixelBufferAccess dst(texture->getLevel(level));
1520 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1521 width != dst.getWidth() ||
1522 height != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1525 texture->allocLevel(level, storageFmt, width, height);
1527 // Copy from current framebuffer.
1528 PixelBufferAccess dst = texture->getLevel(level);
1529 for (int yo = 0; yo < height; yo++)
1530 for (int xo = 0; xo < width; xo++)
1532 if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1533 continue; // Undefined pixel.
1535 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
1538 else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1539 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1540 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1541 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1542 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1543 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1545 // Validate size and level.
1546 RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
1547 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);
1549 TextureCube* texture = unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
1550 tcu::CubeFace face = mapGLCubeFace(target);
1552 if (texture->isImmutable())
1554 RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);
1556 ConstPixelBufferAccess dst(texture->getFace(level, face));
1557 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1558 width != dst.getWidth() ||
1559 height != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1562 texture->allocFace(level, face, storageFmt, width, height);
1564 // Copy from current framebuffer.
1565 PixelBufferAccess dst = texture->getFace(level, face);
1566 for (int yo = 0; yo < height; yo++)
1567 for (int xo = 0; xo < width; xo++)
1569 if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1570 continue; // Undefined pixel.
1572 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
1576 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1579 void ReferenceContext::copyTexSubImage1D (deUint32 target, int level, int xoffset, int x, int y, int width)
1581 TextureUnit& unit = m_textureUnits[m_activeTexture];
1582 rr::MultisampleConstPixelBufferAccess src = getReadColorbuffer();
1584 RC_IF_ERROR(xoffset < 0, GL_INVALID_VALUE, RC_RET_VOID);
1585 RC_IF_ERROR(width < 0, GL_INVALID_VALUE, RC_RET_VOID);
1586 RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1588 if (target == GL_TEXTURE_1D)
1590 Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;
1592 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1594 PixelBufferAccess dst = texture.getLevel(level);
1596 RC_IF_ERROR(xoffset + width > dst.getWidth(), GL_INVALID_VALUE, RC_RET_VOID);
1598 for (int xo = 0; xo < width; xo++)
1600 if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
1603 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo+xoffset, 0);
1607 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1610 void ReferenceContext::copyTexSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int x, int y, int width, int height)
1612 TextureUnit& unit = m_textureUnits[m_activeTexture];
1613 rr::MultisampleConstPixelBufferAccess src = getReadColorbuffer();
1615 RC_IF_ERROR(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE, RC_RET_VOID);
1616 RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
1617 RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1619 if (target == GL_TEXTURE_2D)
1621 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1623 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1625 PixelBufferAccess dst = texture.getLevel(level);
1627 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1628 yoffset + height > dst.getHeight(),
1629 GL_INVALID_VALUE, RC_RET_VOID);
1631 for (int yo = 0; yo < height; yo++)
1632 for (int xo = 0; xo < width; xo++)
1634 if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1637 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
1640 else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1641 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1642 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1643 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1644 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1645 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1647 TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1648 tcu::CubeFace face = mapGLCubeFace(target);
1650 RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);
1652 PixelBufferAccess dst = texture.getFace(level, face);
1654 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1655 yoffset + height > dst.getHeight(),
1656 GL_INVALID_VALUE, RC_RET_VOID);
1658 for (int yo = 0; yo < height; yo++)
1659 for (int xo = 0; xo < width; xo++)
1661 if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1664 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
1668 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1671 void ReferenceContext::copyTexSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height)
1673 DE_UNREF(target && level && xoffset && yoffset && zoffset && x && y && width && height);
1677 void ReferenceContext::texStorage2D (deUint32 target, int levels, deUint32 internalFormat, int width, int height)
1679 TextureUnit& unit = m_textureUnits[m_activeTexture];
1680 TextureFormat storageFmt;
1682 RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
1683 RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);
1685 // Map storage format.
1686 storageFmt = mapInternalFormat(internalFormat);
1687 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1688 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1690 if (target == GL_TEXTURE_2D)
1692 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1694 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height >= m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1695 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1697 texture.clearLevels();
1698 texture.setImmutable();
1700 for (int level = 0; level < levels; level++)
1702 int levelW = de::max(1, width >> level);
1703 int levelH = de::max(1, height >> level);
1705 texture.allocLevel(level, storageFmt, levelW, levelH);
1708 else if (target == GL_TEXTURE_CUBE_MAP)
1710 TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1712 RC_IF_ERROR(width > m_limits.maxTextureCubeSize || height > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
1713 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1715 texture.clearLevels();
1716 texture.setImmutable();
1718 for (int level = 0; level < levels; level++)
1720 int levelW = de::max(1, width >> level);
1721 int levelH = de::max(1, height >> level);
1723 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1724 texture.allocFace(level, (tcu::CubeFace)face, storageFmt, levelW, levelH);
1728 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1731 void ReferenceContext::texStorage3D (deUint32 target, int levels, deUint32 internalFormat, int width, int height, int depth)
1733 TextureUnit& unit = m_textureUnits[m_activeTexture];
1734 TextureFormat storageFmt;
1736 RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
1737 RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);
1739 // Map storage format.
1740 storageFmt = mapInternalFormat(internalFormat);
1741 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1742 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1744 if (target == GL_TEXTURE_2D_ARRAY)
1746 Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;
1748 RC_IF_ERROR(width > m_limits.maxTexture2DSize ||
1749 height >= m_limits.maxTexture2DSize ||
1750 depth >= m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1751 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1753 texture.clearLevels();
1754 texture.setImmutable();
1756 for (int level = 0; level < levels; level++)
1758 int levelW = de::max(1, width >> level);
1759 int levelH = de::max(1, height >> level);
1761 texture.allocLevel(level, storageFmt, levelW, levelH, depth);
1764 else if (target == GL_TEXTURE_3D)
1766 Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;
1768 RC_IF_ERROR(width > m_limits.maxTexture3DSize ||
1769 height > m_limits.maxTexture3DSize ||
1770 depth > m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
1771 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1773 texture.clearLevels();
1774 texture.setImmutable();
1776 for (int level = 0; level < levels; level++)
1778 int levelW = de::max(1, width >> level);
1779 int levelH = de::max(1, height >> level);
1780 int levelD = de::max(1, depth >> level);
1782 texture.allocLevel(level, storageFmt, levelW, levelH, levelD);
1785 else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1787 TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;
1789 RC_IF_ERROR(width != height ||
1791 width > m_limits.maxTexture2DSize ||
1792 depth >= m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1793 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1795 texture.clearLevels();
1796 texture.setImmutable();
1798 for (int level = 0; level < levels; level++)
1800 int levelW = de::max(1, width >> level);
1801 int levelH = de::max(1, height >> level);
1803 texture.allocLevel(level, storageFmt, levelW, levelH, depth);
1807 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1810 // \todo [2014-02-19 pyry] Duplicated with code in gluTextureUtil.hpp
1812 static inline tcu::Sampler::WrapMode mapGLWrapMode (int value)
1816 case GL_CLAMP_TO_EDGE: return tcu::Sampler::CLAMP_TO_EDGE;
1817 case GL_REPEAT: return tcu::Sampler::REPEAT_GL;
1818 case GL_MIRRORED_REPEAT: return tcu::Sampler::MIRRORED_REPEAT_GL;
1819 default: return tcu::Sampler::WRAPMODE_LAST;
1823 static inline tcu::Sampler::FilterMode mapGLFilterMode (int value)
1827 case GL_NEAREST: return tcu::Sampler::NEAREST;
1828 case GL_LINEAR: return tcu::Sampler::LINEAR;
1829 case GL_NEAREST_MIPMAP_NEAREST: return tcu::Sampler::NEAREST_MIPMAP_NEAREST;
1830 case GL_NEAREST_MIPMAP_LINEAR: return tcu::Sampler::NEAREST_MIPMAP_LINEAR;
1831 case GL_LINEAR_MIPMAP_NEAREST: return tcu::Sampler::LINEAR_MIPMAP_NEAREST;
1832 case GL_LINEAR_MIPMAP_LINEAR: return tcu::Sampler::LINEAR_MIPMAP_LINEAR;
1833 default: return tcu::Sampler::FILTERMODE_LAST;
1837 void ReferenceContext::texParameteri (deUint32 target, deUint32 pname, int value)
1839 TextureUnit& unit = m_textureUnits[m_activeTexture];
1840 Texture* texture = DE_NULL;
1844 case GL_TEXTURE_1D: texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex; break;
1845 case GL_TEXTURE_2D: texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex; break;
1846 case GL_TEXTURE_CUBE_MAP: texture = unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex; break;
1847 case GL_TEXTURE_2D_ARRAY: texture = unit.tex2DArrayBinding ? unit.tex2DArrayBinding : &unit.default2DArrayTex; break;
1848 case GL_TEXTURE_3D: texture = unit.tex3DBinding ? unit.tex3DBinding : &unit.default3DTex; break;
1849 case GL_TEXTURE_CUBE_MAP_ARRAY: texture = unit.texCubeArrayBinding ? unit.texCubeArrayBinding : &unit.defaultCubeArrayTex; break;
1851 default: RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1856 case GL_TEXTURE_WRAP_S:
1858 tcu::Sampler::WrapMode wrapS = mapGLWrapMode(value);
1859 RC_IF_ERROR(wrapS == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1860 texture->getSampler().wrapS = wrapS;
1864 case GL_TEXTURE_WRAP_T:
1866 tcu::Sampler::WrapMode wrapT = mapGLWrapMode(value);
1867 RC_IF_ERROR(wrapT == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1868 texture->getSampler().wrapT = wrapT;
1872 case GL_TEXTURE_WRAP_R:
1874 tcu::Sampler::WrapMode wrapR = mapGLWrapMode(value);
1875 RC_IF_ERROR(wrapR == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1876 texture->getSampler().wrapR = wrapR;
1880 case GL_TEXTURE_MIN_FILTER:
1882 tcu::Sampler::FilterMode minMode = mapGLFilterMode(value);
1883 RC_IF_ERROR(minMode == tcu::Sampler::FILTERMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1884 texture->getSampler().minFilter = minMode;
1888 case GL_TEXTURE_MAG_FILTER:
1890 tcu::Sampler::FilterMode magMode = mapGLFilterMode(value);
1891 RC_IF_ERROR(magMode != tcu::Sampler::LINEAR && magMode != tcu::Sampler::NEAREST,
1892 GL_INVALID_VALUE, RC_RET_VOID);
1893 texture->getSampler().magFilter = magMode;
1897 case GL_TEXTURE_MAX_LEVEL:
1899 RC_IF_ERROR(value < 0, GL_INVALID_VALUE, RC_RET_VOID);
1900 texture->setMaxLevel(value);
1905 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1909 static inline Framebuffer::AttachmentPoint mapGLAttachmentPoint (deUint32 attachment)
1913 case GL_COLOR_ATTACHMENT0: return Framebuffer::ATTACHMENTPOINT_COLOR0;
1914 case GL_DEPTH_ATTACHMENT: return Framebuffer::ATTACHMENTPOINT_DEPTH;
1915 case GL_STENCIL_ATTACHMENT: return Framebuffer::ATTACHMENTPOINT_STENCIL;
1916 default: return Framebuffer::ATTACHMENTPOINT_LAST;
1920 static inline Framebuffer::TexTarget mapGLFboTexTarget (deUint32 target)
1924 case GL_TEXTURE_2D: return Framebuffer::TEXTARGET_2D;
1925 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X;
1926 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y;
1927 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z;
1928 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X;
1929 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y;
1930 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z;
1931 default: return Framebuffer::TEXTARGET_LAST;
1935 void ReferenceContext::acquireFboAttachmentReference (const Framebuffer::Attachment& attachment)
1937 switch (attachment.type)
1939 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
1941 TCU_CHECK(attachment.name != 0);
1942 Texture* texture = m_textures.find(attachment.name);
1944 m_textures.acquireReference(texture);
1948 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
1950 TCU_CHECK(attachment.name != 0);
1951 Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
1953 m_renderbuffers.acquireReference(rbo);
1958 break; // Silently ignore
1962 void ReferenceContext::releaseFboAttachmentReference (const Framebuffer::Attachment& attachment)
1964 switch (attachment.type)
1966 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
1968 TCU_CHECK(attachment.name != 0);
1969 Texture* texture = m_textures.find(attachment.name);
1971 m_textures.releaseReference(texture);
1975 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
1977 TCU_CHECK(attachment.name != 0);
1978 Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
1980 m_renderbuffers.releaseReference(rbo);
1985 break; // Silently ignore
1989 void ReferenceContext::framebufferTexture2D (deUint32 target, deUint32 attachment, deUint32 textarget, deUint32 texture, int level)
1991 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
1993 // Attach to both depth and stencil.
1994 framebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textarget, texture, level);
1995 framebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textarget, texture, level);
1999 Framebuffer::AttachmentPoint point = mapGLAttachmentPoint(attachment);
2000 Texture* texObj = DE_NULL;
2001 Framebuffer::TexTarget fboTexTarget = mapGLFboTexTarget(textarget);
2003 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
2004 target != GL_DRAW_FRAMEBUFFER &&
2005 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2006 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2008 // Select binding point.
2009 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2010 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2012 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2013 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2014 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2018 texObj = m_textures.find(texture);
2020 RC_IF_ERROR(!texObj, GL_INVALID_OPERATION, RC_RET_VOID);
2021 RC_IF_ERROR(level != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.
2023 if (texObj->getType() == Texture::TYPE_2D)
2024 RC_IF_ERROR(fboTexTarget != Framebuffer::TEXTARGET_2D, GL_INVALID_OPERATION, RC_RET_VOID);
2027 TCU_CHECK(texObj->getType() == Texture::TYPE_CUBE_MAP);
2028 if (!deInRange32(fboTexTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X, Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
2029 RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
2033 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2034 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2035 releaseFboAttachmentReference(fboAttachment);
2036 fboAttachment = Framebuffer::Attachment();
2040 fboAttachment.type = Framebuffer::ATTACHMENTTYPE_TEXTURE;
2041 fboAttachment.name = texObj->getName();
2042 fboAttachment.texTarget = fboTexTarget;
2043 fboAttachment.level = level;
2045 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2046 acquireFboAttachmentReference(fboAttachment);
2051 void ReferenceContext::framebufferTextureLayer (deUint32 target, deUint32 attachment, deUint32 texture, int level, int layer)
2053 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
2055 // Attach to both depth and stencil.
2056 framebufferTextureLayer(target, GL_DEPTH_ATTACHMENT, texture, level, layer);
2057 framebufferTextureLayer(target, GL_STENCIL_ATTACHMENT, texture, level, layer);
2061 Framebuffer::AttachmentPoint point = mapGLAttachmentPoint(attachment);
2062 Texture* texObj = DE_NULL;
2064 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
2065 target != GL_DRAW_FRAMEBUFFER &&
2066 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2067 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2069 // Select binding point.
2070 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2071 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2073 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2074 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2075 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2079 texObj = m_textures.find(texture);
2081 RC_IF_ERROR(!texObj, GL_INVALID_OPERATION, RC_RET_VOID);
2082 RC_IF_ERROR(level != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.
2084 RC_IF_ERROR(texObj->getType() != Texture::TYPE_2D_ARRAY &&
2085 texObj->getType() != Texture::TYPE_3D &&
2086 texObj->getType() != Texture::TYPE_CUBE_MAP_ARRAY, GL_INVALID_OPERATION, RC_RET_VOID);
2088 if (texObj->getType() == Texture::TYPE_2D_ARRAY || texObj->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2090 RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_ARRAY_TEXTURE_LAYERS), GL_INVALID_VALUE, RC_RET_VOID);
2091 RC_IF_ERROR((level < 0) || (level > deLog2Floor32(GL_MAX_TEXTURE_SIZE)),GL_INVALID_VALUE, RC_RET_VOID);
2093 else if (texObj->getType() == Texture::TYPE_3D)
2095 RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_3D_TEXTURE_SIZE), GL_INVALID_VALUE, RC_RET_VOID);
2096 RC_IF_ERROR((level < 0) || (level > deLog2Floor32(GL_MAX_3D_TEXTURE_SIZE)), GL_INVALID_VALUE, RC_RET_VOID);
2100 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2101 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2102 releaseFboAttachmentReference(fboAttachment);
2103 fboAttachment = Framebuffer::Attachment();
2107 fboAttachment.type = Framebuffer::ATTACHMENTTYPE_TEXTURE;
2108 fboAttachment.name = texObj->getName();
2109 fboAttachment.texTarget = texLayeredTypeToTarget(texObj->getType());
2110 fboAttachment.level = level;
2111 fboAttachment.layer = layer;
2113 DE_ASSERT(fboAttachment.texTarget != Framebuffer::TEXTARGET_LAST);
2115 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2116 acquireFboAttachmentReference(fboAttachment);
2121 void ReferenceContext::framebufferRenderbuffer (deUint32 target, deUint32 attachment, deUint32 renderbuffertarget, deUint32 renderbuffer)
2123 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
2125 // Attach both to depth and stencil.
2126 framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, renderbuffer);
2127 framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, renderbuffer);
2131 Framebuffer::AttachmentPoint point = mapGLAttachmentPoint(attachment);
2132 Renderbuffer* rbo = DE_NULL;
2134 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
2135 target != GL_DRAW_FRAMEBUFFER &&
2136 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2137 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2139 // Select binding point.
2140 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2141 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2143 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2144 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2145 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2147 if (renderbuffer != 0)
2149 rbo = m_renderbuffers.find(renderbuffer);
2151 RC_IF_ERROR(renderbuffertarget != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2152 RC_IF_ERROR(!rbo, GL_INVALID_OPERATION, RC_RET_VOID);
2155 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2156 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2157 releaseFboAttachmentReference(fboAttachment);
2158 fboAttachment = Framebuffer::Attachment();
2162 fboAttachment.type = Framebuffer::ATTACHMENTTYPE_RENDERBUFFER;
2163 fboAttachment.name = rbo->getName();
2165 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2166 acquireFboAttachmentReference(fboAttachment);
2171 deUint32 ReferenceContext::checkFramebufferStatus (deUint32 target)
2173 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
2174 target != GL_DRAW_FRAMEBUFFER &&
2175 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, 0);
2177 // Select binding point.
2178 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2180 // Default framebuffer is always complete.
2181 if (!framebufferBinding)
2182 return GL_FRAMEBUFFER_COMPLETE;
2186 bool hasAttachment = false;
2187 bool attachmentComplete = true;
2188 bool dimensionsOk = true;
2190 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
2192 const Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
2193 int attachmentWidth = 0;
2194 int attachmentHeight = 0;
2195 tcu::TextureFormat attachmentFormat;
2197 if (attachment.type == Framebuffer::ATTACHMENTTYPE_TEXTURE)
2199 const Texture* texture = m_textures.find(attachment.name);
2200 tcu::ConstPixelBufferAccess level;
2203 if (attachment.texTarget == Framebuffer::TEXTARGET_2D)
2205 DE_ASSERT(texture->getType() == Texture::TYPE_2D);
2206 const Texture2D* tex2D = static_cast<const Texture2D*>(texture);
2208 if (tex2D->hasLevel(attachment.level))
2209 level = tex2D->getLevel(attachment.level);
2211 else if (deInRange32(attachment.texTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X,
2212 Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
2214 DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP);
2216 const TextureCube* texCube = static_cast<const TextureCube*>(texture);
2217 const tcu::CubeFace face = texTargetToFace(attachment.texTarget);
2218 TCU_CHECK(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
2220 if (texCube->hasFace(attachment.level, face))
2221 level = texCube->getFace(attachment.level, face);
2223 else if (attachment.texTarget == Framebuffer::TEXTARGET_2D_ARRAY)
2225 DE_ASSERT(texture->getType() == Texture::TYPE_2D_ARRAY);
2226 const Texture2DArray* tex2DArr = static_cast<const Texture2DArray*>(texture);
2228 if (tex2DArr->hasLevel(attachment.level))
2229 level = tex2DArr->getLevel(attachment.level); // \note Slice doesn't matter here.
2231 else if (attachment.texTarget == Framebuffer::TEXTARGET_3D)
2233 DE_ASSERT(texture->getType() == Texture::TYPE_3D);
2234 const Texture3D* tex3D = static_cast<const Texture3D*>(texture);
2236 if (tex3D->hasLevel(attachment.level))
2237 level = tex3D->getLevel(attachment.level); // \note Slice doesn't matter here.
2239 else if (attachment.texTarget == Framebuffer::TEXTARGET_CUBE_MAP_ARRAY)
2241 DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY);
2242 const TextureCubeArray* texCubeArr = static_cast<const TextureCubeArray*>(texture);
2244 if (texCubeArr->hasLevel(attachment.level))
2245 level = texCubeArr->getLevel(attachment.level); // \note Slice doesn't matter here.
2248 TCU_FAIL("Framebuffer attached to a texture but no valid target specified");
2250 attachmentWidth = level.getWidth();
2251 attachmentHeight = level.getHeight();
2252 attachmentFormat = level.getFormat();
2254 else if (attachment.type == Framebuffer::ATTACHMENTTYPE_RENDERBUFFER)
2256 const Renderbuffer* renderbuffer = m_renderbuffers.find(attachment.name);
2257 TCU_CHECK(renderbuffer);
2259 attachmentWidth = renderbuffer->getWidth();
2260 attachmentHeight = renderbuffer->getHeight();
2261 attachmentFormat = renderbuffer->getFormat();
2265 TCU_CHECK(attachment.type == Framebuffer::ATTACHMENTTYPE_LAST);
2266 continue; // Skip rest of checks.
2269 if (!hasAttachment && attachmentWidth > 0 && attachmentHeight > 0)
2271 width = attachmentWidth;
2272 height = attachmentHeight;
2273 hasAttachment = true;
2275 else if (attachmentWidth != width || attachmentHeight != height)
2276 dimensionsOk = false;
2278 // Validate attachment point compatibility.
2279 switch (attachmentFormat.order)
2281 case TextureFormat::R:
2282 case TextureFormat::RG:
2283 case TextureFormat::RGB:
2284 case TextureFormat::RGBA:
2285 case TextureFormat::sRGB:
2286 case TextureFormat::sRGBA:
2287 if (point != Framebuffer::ATTACHMENTPOINT_COLOR0)
2288 attachmentComplete = false;
2291 case TextureFormat::D:
2292 if (point != Framebuffer::ATTACHMENTPOINT_DEPTH)
2293 attachmentComplete = false;
2296 case TextureFormat::S:
2297 if (point != Framebuffer::ATTACHMENTPOINT_STENCIL)
2298 attachmentComplete = false;
2301 case TextureFormat::DS:
2302 if (point != Framebuffer::ATTACHMENTPOINT_DEPTH &&
2303 point != Framebuffer::ATTACHMENTPOINT_STENCIL)
2304 attachmentComplete = false;
2308 TCU_FAIL("Unsupported attachment channel order");
2312 if (!attachmentComplete)
2313 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2314 else if (!hasAttachment)
2315 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
2316 else if (!dimensionsOk)
2317 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
2319 return GL_FRAMEBUFFER_COMPLETE;
2322 void ReferenceContext::getFramebufferAttachmentParameteriv (deUint32 target, deUint32 attachment, deUint32 pname, int* params)
2324 DE_UNREF(target && attachment && pname && params);
2325 TCU_CHECK(false); // \todo [pyry] Implement
2328 void ReferenceContext::renderbufferStorage (deUint32 target, deUint32 internalformat, int width, int height)
2330 TextureFormat format = glu::mapGLInternalFormat(internalformat);
2332 RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2333 RC_IF_ERROR(!m_renderbufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2334 RC_IF_ERROR(!deInRange32(width, 0, m_limits.maxRenderbufferSize) ||
2335 !deInRange32(height, 0, m_limits.maxRenderbufferSize),
2336 GL_INVALID_OPERATION, RC_RET_VOID);
2337 RC_IF_ERROR(format.order == TextureFormat::CHANNELORDER_LAST ||
2338 format.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2340 m_renderbufferBinding->setStorage(format, (int)width, (int)height);
2343 void ReferenceContext::renderbufferStorageMultisample (deUint32 target, int samples, deUint32 internalFormat, int width, int height)
2345 // \todo [2012-04-07 pyry] Implement MSAA support.
2347 renderbufferStorage(target, internalFormat, width, height);
2350 tcu::PixelBufferAccess ReferenceContext::getFboAttachment (const rc::Framebuffer& framebuffer, rc::Framebuffer::AttachmentPoint point)
2352 const Framebuffer::Attachment& attachment = framebuffer.getAttachment(point);
2354 switch (attachment.type)
2356 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
2358 Texture* texture = m_textures.find(attachment.name);
2361 if (texture->getType() == Texture::TYPE_2D)
2363 if (Texture2D* texture2D = dynamic_cast<Texture2D*>(texture))
2364 return texture2D->getLevel(attachment.level);
2366 return nullAccess();
2368 else if (texture->getType() == Texture::TYPE_CUBE_MAP)
2370 if (TextureCube* cubeMap = dynamic_cast<TextureCube*>(texture))
2371 return cubeMap->getFace(attachment.level, texTargetToFace(attachment.texTarget));
2373 return nullAccess();
2375 else if (texture->getType() == Texture::TYPE_2D_ARRAY ||
2376 texture->getType() == Texture::TYPE_3D ||
2377 texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2379 tcu::PixelBufferAccess level;
2381 if (texture->getType() == Texture::TYPE_2D_ARRAY)
2383 if (Texture2DArray* texture2DArray = dynamic_cast<Texture2DArray*>(texture))
2384 level = texture2DArray->getLevel(attachment.level);
2386 else if (texture->getType() == Texture::TYPE_3D)
2388 if (Texture3D* texture3D = dynamic_cast<Texture3D*>(texture))
2389 level = texture3D->getLevel(attachment.level);
2391 else if (texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2393 if (TextureCubeArray* cubeArray = dynamic_cast<TextureCubeArray*>(texture))
2394 level = cubeArray->getLevel(attachment.level);
2397 void* layerData = static_cast<deUint8*>(level.getDataPtr()) + level.getSlicePitch() * attachment.layer;
2399 return tcu::PixelBufferAccess(level.getFormat(), level.getWidth(), level.getHeight(), 1, level.getRowPitch(), 0, layerData);
2402 return nullAccess();
2405 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
2407 Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
2410 return rbo->getAccess();
2414 return nullAccess();
2418 const Texture2D& ReferenceContext::getTexture2D (int unitNdx) const
2420 const TextureUnit& unit = m_textureUnits[unitNdx];
2421 return unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
2424 const TextureCube& ReferenceContext::getTextureCube (int unitNdx) const
2426 const TextureUnit& unit = m_textureUnits[unitNdx];
2427 return unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
2430 static bool isValidBufferTarget (deUint32 target)
2434 case GL_ARRAY_BUFFER:
2435 case GL_COPY_READ_BUFFER:
2436 case GL_COPY_WRITE_BUFFER:
2437 case GL_DRAW_INDIRECT_BUFFER:
2438 case GL_ELEMENT_ARRAY_BUFFER:
2439 case GL_PIXEL_PACK_BUFFER:
2440 case GL_PIXEL_UNPACK_BUFFER:
2441 case GL_TRANSFORM_FEEDBACK_BUFFER:
2442 case GL_UNIFORM_BUFFER:
2450 void ReferenceContext::setBufferBinding (deUint32 target, DataBuffer* buffer)
2452 DataBuffer** bindingPoint = DE_NULL;
2453 VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2457 case GL_ARRAY_BUFFER: bindingPoint = &m_arrayBufferBinding; break;
2458 case GL_COPY_READ_BUFFER: bindingPoint = &m_copyReadBufferBinding; break;
2459 case GL_COPY_WRITE_BUFFER: bindingPoint = &m_copyWriteBufferBinding; break;
2460 case GL_DRAW_INDIRECT_BUFFER: bindingPoint = &m_drawIndirectBufferBinding; break;
2461 case GL_ELEMENT_ARRAY_BUFFER: bindingPoint = &vertexArrayObject->m_elementArrayBufferBinding; break;
2462 case GL_PIXEL_PACK_BUFFER: bindingPoint = &m_pixelPackBufferBinding; break;
2463 case GL_PIXEL_UNPACK_BUFFER: bindingPoint = &m_pixelUnpackBufferBinding; break;
2464 case GL_TRANSFORM_FEEDBACK_BUFFER: bindingPoint = &m_transformFeedbackBufferBinding; break;
2465 case GL_UNIFORM_BUFFER: bindingPoint = &m_uniformBufferBinding; break;
2473 m_buffers.releaseReference(*bindingPoint);
2474 *bindingPoint = DE_NULL;
2478 m_buffers.acquireReference(buffer);
2480 *bindingPoint = buffer;
2483 DataBuffer* ReferenceContext::getBufferBinding (deUint32 target) const
2485 const VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2489 case GL_ARRAY_BUFFER: return m_arrayBufferBinding;
2490 case GL_COPY_READ_BUFFER: return m_copyReadBufferBinding;
2491 case GL_COPY_WRITE_BUFFER: return m_copyWriteBufferBinding;
2492 case GL_DRAW_INDIRECT_BUFFER: return m_drawIndirectBufferBinding;
2493 case GL_ELEMENT_ARRAY_BUFFER: return vertexArrayObject->m_elementArrayBufferBinding;
2494 case GL_PIXEL_PACK_BUFFER: return m_pixelPackBufferBinding;
2495 case GL_PIXEL_UNPACK_BUFFER: return m_pixelUnpackBufferBinding;
2496 case GL_TRANSFORM_FEEDBACK_BUFFER: return m_transformFeedbackBufferBinding;
2497 case GL_UNIFORM_BUFFER: return m_uniformBufferBinding;
2504 void ReferenceContext::bindBuffer (deUint32 target, deUint32 buffer)
2506 RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2508 rc::DataBuffer* bufObj = DE_NULL;
2512 bufObj = m_buffers.find(buffer);
2515 bufObj = new DataBuffer(buffer);
2516 m_buffers.insert(bufObj);
2520 setBufferBinding(target, bufObj);
2523 void ReferenceContext::genBuffers (int numBuffers, deUint32* buffers)
2525 RC_IF_ERROR(!buffers, GL_INVALID_VALUE, RC_RET_VOID);
2527 for (int ndx = 0; ndx < numBuffers; ndx++)
2528 buffers[ndx] = m_buffers.allocateName();
2531 void ReferenceContext::deleteBuffers (int numBuffers, const deUint32* buffers)
2533 RC_IF_ERROR(numBuffers < 0, GL_INVALID_VALUE, RC_RET_VOID);
2535 for (int ndx = 0; ndx < numBuffers; ndx++)
2537 deUint32 buffer = buffers[ndx];
2538 DataBuffer* bufObj = DE_NULL;
2543 bufObj = m_buffers.find(buffer);
2546 deleteBuffer(bufObj);
2550 void ReferenceContext::deleteBuffer (DataBuffer* buffer)
2552 static const deUint32 bindingPoints[] =
2555 GL_COPY_READ_BUFFER,
2556 GL_COPY_WRITE_BUFFER,
2557 GL_DRAW_INDIRECT_BUFFER,
2558 GL_ELEMENT_ARRAY_BUFFER,
2559 GL_PIXEL_PACK_BUFFER,
2560 GL_PIXEL_UNPACK_BUFFER,
2561 GL_TRANSFORM_FEEDBACK_BUFFER,
2565 for (int bindingNdx = 0; bindingNdx < DE_LENGTH_OF_ARRAY(bindingPoints); bindingNdx++)
2567 if (getBufferBinding(bindingPoints[bindingNdx]) == buffer)
2568 setBufferBinding(bindingPoints[bindingNdx], DE_NULL);
2572 vector<VertexArray*> vertexArrays;
2573 m_vertexArrays.getAll(vertexArrays);
2574 vertexArrays.push_back(&m_clientVertexArray);
2576 for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
2578 if ((*i)->m_elementArrayBufferBinding == buffer)
2580 m_buffers.releaseReference(buffer);
2581 (*i)->m_elementArrayBufferBinding = DE_NULL;
2584 for (size_t vertexAttribNdx = 0; vertexAttribNdx < (*i)->m_arrays.size(); ++vertexAttribNdx)
2586 if ((*i)->m_arrays[vertexAttribNdx].bufferBinding == buffer)
2588 m_buffers.releaseReference(buffer);
2589 (*i)->m_arrays[vertexAttribNdx].bufferDeleted = true;
2590 (*i)->m_arrays[vertexAttribNdx].bufferBinding = DE_NULL;
2596 DE_ASSERT(buffer->getRefCount() == 1);
2597 m_buffers.releaseReference(buffer);
2600 void ReferenceContext::bufferData (deUint32 target, deIntptr size, const void* data, deUint32 usage)
2602 RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2603 RC_IF_ERROR(size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2607 DataBuffer* buffer = getBufferBinding(target);
2608 RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2610 DE_ASSERT((deIntptr)(int)size == size);
2611 buffer->setStorage((int)size);
2613 deMemcpy(buffer->getData(), data, (int)size);
2616 void ReferenceContext::bufferSubData (deUint32 target, deIntptr offset, deIntptr size, const void* data)
2618 RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2619 RC_IF_ERROR(offset < 0 || size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2621 DataBuffer* buffer = getBufferBinding(target);
2623 RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2624 RC_IF_ERROR((int)(offset+size) > buffer->getSize(), GL_INVALID_VALUE, RC_RET_VOID);
2626 deMemcpy(buffer->getData()+offset, data, (int)size);
2629 void ReferenceContext::clearColor (float red, float green, float blue, float alpha)
2631 m_clearColor = Vec4(de::clamp(red, 0.0f, 1.0f),
2632 de::clamp(green, 0.0f, 1.0f),
2633 de::clamp(blue, 0.0f, 1.0f),
2634 de::clamp(alpha, 0.0f, 1.0f));
2637 void ReferenceContext::clearDepthf (float depth)
2639 m_clearDepth = de::clamp(depth, 0.0f, 1.0f);
2642 void ReferenceContext::clearStencil (int stencil)
2644 m_clearStencil = stencil;
2647 void ReferenceContext::scissor (int x, int y, int width, int height)
2649 RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
2650 m_scissorBox = IVec4(x, y, width, height);
2653 void ReferenceContext::enable (deUint32 cap)
2657 case GL_BLEND: m_blendEnabled = true; break;
2658 case GL_SCISSOR_TEST: m_scissorEnabled = true; break;
2659 case GL_DEPTH_TEST: m_depthTestEnabled = true; break;
2660 case GL_STENCIL_TEST: m_stencilTestEnabled = true; break;
2661 case GL_POLYGON_OFFSET_FILL: m_polygonOffsetFillEnabled = true; break;
2663 case GL_FRAMEBUFFER_SRGB:
2664 if (glu::isContextTypeGLCore(getType()))
2666 m_sRGBUpdateEnabled = true;
2669 setError(GL_INVALID_ENUM);
2672 case GL_DEPTH_CLAMP:
2673 if (glu::isContextTypeGLCore(getType()))
2675 m_depthClampEnabled = true;
2678 setError(GL_INVALID_ENUM);
2682 // Not implemented - just ignored.
2685 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2686 if (!glu::isContextTypeGLCore(getType()))
2688 m_primitiveRestartFixedIndex = true;
2691 setError(GL_INVALID_ENUM);
2694 case GL_PRIMITIVE_RESTART:
2695 if (glu::isContextTypeGLCore(getType()))
2697 m_primitiveRestartSettableIndex = true;
2700 setError(GL_INVALID_ENUM);
2704 setError(GL_INVALID_ENUM);
2709 void ReferenceContext::disable (deUint32 cap)
2713 case GL_BLEND: m_blendEnabled = false; break;
2714 case GL_SCISSOR_TEST: m_scissorEnabled = false; break;
2715 case GL_DEPTH_TEST: m_depthTestEnabled = false; break;
2716 case GL_STENCIL_TEST: m_stencilTestEnabled = false; break;
2717 case GL_POLYGON_OFFSET_FILL: m_polygonOffsetFillEnabled = false; break;
2719 case GL_FRAMEBUFFER_SRGB:
2720 if (glu::isContextTypeGLCore(getType()))
2722 m_sRGBUpdateEnabled = false;
2725 setError(GL_INVALID_ENUM);
2728 case GL_DEPTH_CLAMP:
2729 if (glu::isContextTypeGLCore(getType()))
2731 m_depthClampEnabled = false;
2734 setError(GL_INVALID_ENUM);
2740 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2741 if (!glu::isContextTypeGLCore(getType()))
2743 m_primitiveRestartFixedIndex = false;
2746 setError(GL_INVALID_ENUM);
2749 case GL_PRIMITIVE_RESTART:
2750 if (glu::isContextTypeGLCore(getType()))
2752 m_primitiveRestartSettableIndex = false;
2755 setError(GL_INVALID_ENUM);
2759 setError(GL_INVALID_ENUM);
2764 static bool isValidCompareFunc (deUint32 func)
2783 static bool isValidStencilOp (deUint32 op)
2802 void ReferenceContext::stencilFunc (deUint32 func, int ref, deUint32 mask)
2804 stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
2807 void ReferenceContext::stencilFuncSeparate (deUint32 face, deUint32 func, int ref, deUint32 mask)
2809 const bool setFront = face == GL_FRONT || face == GL_FRONT_AND_BACK;
2810 const bool setBack = face == GL_BACK || face == GL_FRONT_AND_BACK;
2812 RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2813 RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2815 for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2817 if ((type == rr::FACETYPE_FRONT && setFront) ||
2818 (type == rr::FACETYPE_BACK && setBack))
2820 m_stencil[type].func = func;
2821 m_stencil[type].ref = ref;
2822 m_stencil[type].opMask = mask;
2827 void ReferenceContext::stencilOp (deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2829 stencilOpSeparate(GL_FRONT_AND_BACK, sfail, dpfail, dppass);
2832 void ReferenceContext::stencilOpSeparate (deUint32 face, deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2834 const bool setFront = face == GL_FRONT || face == GL_FRONT_AND_BACK;
2835 const bool setBack = face == GL_BACK || face == GL_FRONT_AND_BACK;
2837 RC_IF_ERROR(!isValidStencilOp(sfail) ||
2838 !isValidStencilOp(dpfail) ||
2839 !isValidStencilOp(dppass),
2840 GL_INVALID_ENUM, RC_RET_VOID);
2841 RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2843 for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2845 if ((type == rr::FACETYPE_FRONT && setFront) ||
2846 (type == rr::FACETYPE_BACK && setBack))
2848 m_stencil[type].opStencilFail = sfail;
2849 m_stencil[type].opDepthFail = dpfail;
2850 m_stencil[type].opDepthPass = dppass;
2855 void ReferenceContext::depthFunc (deUint32 func)
2857 RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2861 void ReferenceContext::depthRangef (float n, float f)
2863 m_depthRangeNear = de::clamp(n, 0.0f, 1.0f);
2864 m_depthRangeFar = de::clamp(f, 0.0f, 1.0f);
2867 void ReferenceContext::depthRange (double n, double f)
2869 depthRangef((float)n, (float)f);
2872 void ReferenceContext::polygonOffset (float factor, float units)
2874 m_polygonOffsetFactor = factor;
2875 m_polygonOffsetUnits = units;
2878 void ReferenceContext::provokingVertex (deUint32 convention)
2881 DE_ASSERT(glu::isContextTypeGLCore(getType()));
2885 case GL_FIRST_VERTEX_CONVENTION: m_provokingFirstVertexConvention = true; break;
2886 case GL_LAST_VERTEX_CONVENTION: m_provokingFirstVertexConvention = false; break;
2889 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
2893 void ReferenceContext::primitiveRestartIndex (deUint32 index)
2896 DE_ASSERT(glu::isContextTypeGLCore(getType()));
2897 m_primitiveRestartIndex = index;
2900 static inline bool isValidBlendEquation (deUint32 mode)
2902 return mode == GL_FUNC_ADD ||
2903 mode == GL_FUNC_SUBTRACT ||
2904 mode == GL_FUNC_REVERSE_SUBTRACT ||
2909 static bool isValidBlendFactor (deUint32 factor)
2916 case GL_ONE_MINUS_SRC_COLOR:
2918 case GL_ONE_MINUS_DST_COLOR:
2920 case GL_ONE_MINUS_SRC_ALPHA:
2922 case GL_ONE_MINUS_DST_ALPHA:
2923 case GL_CONSTANT_COLOR:
2924 case GL_ONE_MINUS_CONSTANT_COLOR:
2925 case GL_CONSTANT_ALPHA:
2926 case GL_ONE_MINUS_CONSTANT_ALPHA:
2927 case GL_SRC_ALPHA_SATURATE:
2935 void ReferenceContext::blendEquation (deUint32 mode)
2937 RC_IF_ERROR(!isValidBlendEquation(mode), GL_INVALID_ENUM, RC_RET_VOID);
2939 m_blendModeRGB = mode;
2940 m_blendModeAlpha = mode;
2943 void ReferenceContext::blendEquationSeparate (deUint32 modeRGB, deUint32 modeAlpha)
2945 RC_IF_ERROR(!isValidBlendEquation(modeRGB) ||
2946 !isValidBlendEquation(modeAlpha),
2947 GL_INVALID_ENUM, RC_RET_VOID);
2949 m_blendModeRGB = modeRGB;
2950 m_blendModeAlpha = modeAlpha;
2953 void ReferenceContext::blendFunc (deUint32 src, deUint32 dst)
2955 RC_IF_ERROR(!isValidBlendFactor(src) ||
2956 !isValidBlendFactor(dst),
2957 GL_INVALID_ENUM, RC_RET_VOID);
2959 m_blendFactorSrcRGB = src;
2960 m_blendFactorSrcAlpha = src;
2961 m_blendFactorDstRGB = dst;
2962 m_blendFactorDstAlpha = dst;
2965 void ReferenceContext::blendFuncSeparate (deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
2967 RC_IF_ERROR(!isValidBlendFactor(srcRGB) ||
2968 !isValidBlendFactor(dstRGB) ||
2969 !isValidBlendFactor(srcAlpha) ||
2970 !isValidBlendFactor(dstAlpha),
2971 GL_INVALID_ENUM, RC_RET_VOID);
2973 m_blendFactorSrcRGB = srcRGB;
2974 m_blendFactorSrcAlpha = srcAlpha;
2975 m_blendFactorDstRGB = dstRGB;
2976 m_blendFactorDstAlpha = dstAlpha;
2979 void ReferenceContext::blendColor (float red, float green, float blue, float alpha)
2981 m_blendColor = Vec4(de::clamp(red, 0.0f, 1.0f),
2982 de::clamp(green, 0.0f, 1.0f),
2983 de::clamp(blue, 0.0f, 1.0f),
2984 de::clamp(alpha, 0.0f, 1.0f));
2987 void ReferenceContext::colorMask (deBool r, deBool g, deBool b, deBool a)
2989 m_colorMask = tcu::BVec4(!!r, !!g, !!b, !!a);
2992 void ReferenceContext::depthMask (deBool mask)
2994 m_depthMask = !!mask;
2997 void ReferenceContext::stencilMask (deUint32 mask)
2999 stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
3002 void ReferenceContext::stencilMaskSeparate (deUint32 face, deUint32 mask)
3004 const bool setFront = face == GL_FRONT || face == GL_FRONT_AND_BACK;
3005 const bool setBack = face == GL_BACK || face == GL_FRONT_AND_BACK;
3007 RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
3009 if (setFront) m_stencil[rr::FACETYPE_FRONT].writeMask = mask;
3010 if (setBack) m_stencil[rr::FACETYPE_BACK].writeMask = mask;
3013 static int getNumStencilBits (const tcu::TextureFormat& format)
3015 switch (format.order)
3017 case tcu::TextureFormat::S:
3018 switch (format.type)
3020 case tcu::TextureFormat::UNSIGNED_INT8: return 8;
3021 case tcu::TextureFormat::UNSIGNED_INT16: return 16;
3022 case tcu::TextureFormat::UNSIGNED_INT32: return 32;
3028 case tcu::TextureFormat::DS:
3029 switch (format.type)
3031 case tcu::TextureFormat::UNSIGNED_INT_24_8: return 8;
3032 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: return 8;
3044 static inline deUint32 maskStencil (int numBits, deUint32 s)
3046 return s & deBitMask32(0, numBits);
3049 static inline void writeMaskedStencil (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, deUint32 stencil, deUint32 writeMask)
3051 DE_ASSERT(access.raw().getFormat().order == tcu::TextureFormat::S);
3053 const deUint32 oldVal = access.raw().getPixelUint(s, x, y).x();
3054 const deUint32 newVal = (oldVal & ~writeMask) | (stencil & writeMask);
3055 access.raw().setPixel(tcu::UVec4(newVal, 0u, 0u, 0u), s, x, y);
3058 static inline void writeDepthOnly (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, float depth)
3060 access.raw().setPixDepth(depth, s, x, y);
3063 static rr::MultisamplePixelBufferAccess getDepthMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
3065 return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_DEPTH));
3068 static rr::MultisamplePixelBufferAccess getStencilMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
3070 return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_STENCIL));
3073 deUint32 ReferenceContext::blitResolveMultisampleFramebuffer (deUint32 mask, const IVec4& srcRect, const IVec4& dstRect, bool flipX, bool flipY)
3075 if (mask & GL_COLOR_BUFFER_BIT)
3077 rr::MultisampleConstPixelBufferAccess src = rr::getSubregion(getReadColorbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3078 tcu::PixelBufferAccess dst = tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3079 tcu::TextureChannelClass dstClass = tcu::getTextureChannelClass(dst.getFormat().type);
3080 bool dstIsFloat = dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT ||
3081 dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
3082 dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3083 bool srcIsSRGB = tcu::isSRGB(src.raw().getFormat());
3084 bool dstIsSRGB = tcu::isSRGB(dst.getFormat());
3085 const bool convertSRGB = m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3089 tcu::ConstPixelBufferAccess srcRaw = src.raw();
3090 tcu::TextureFormat srcFmt = toNonSRGBFormat(srcRaw.getFormat());
3092 srcRaw = tcu::ConstPixelBufferAccess(srcFmt, srcRaw.getWidth(), srcRaw.getHeight(), srcRaw.getDepth(), srcRaw.getRowPitch(), srcRaw.getSlicePitch(), srcRaw.getDataPtr());
3093 src = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(srcRaw);
3095 dst = tcu::PixelBufferAccess(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3098 for (int x = 0; x < dstRect.z(); ++x)
3099 for (int y = 0; y < dstRect.w(); ++y)
3101 int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3102 int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3104 if (dstIsFloat || srcIsSRGB)
3106 Vec4 p = src.raw().getPixel(0, srcX,srcY);
3107 dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, x, y);
3110 dst.setPixel(src.raw().getPixelInt(0, srcX, srcY), x, y);
3114 if (mask & GL_DEPTH_BUFFER_BIT)
3116 rr::MultisampleConstPixelBufferAccess src = rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3117 rr::MultisamplePixelBufferAccess dst = rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3119 for (int x = 0; x < dstRect.z(); ++x)
3120 for (int y = 0; y < dstRect.w(); ++y)
3122 int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3123 int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3125 writeDepthOnly(dst, 0, x, y, src.raw().getPixel(0, srcX, srcY).x());
3129 if (mask & GL_STENCIL_BUFFER_BIT)
3131 rr::MultisampleConstPixelBufferAccess src = getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3132 rr::MultisamplePixelBufferAccess dst = getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3134 for (int x = 0; x < dstRect.z(); ++x)
3135 for (int y = 0; y < dstRect.w(); ++y)
3137 int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3138 int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3139 deUint32 srcStencil = src.raw().getPixelUint(0, srcX, srcY).x();
3141 writeMaskedStencil(dst, 0, x, y, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3148 void ReferenceContext::blitFramebuffer (int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, deUint32 mask, deUint32 filter)
3150 // p0 in inclusive, p1 exclusive.
3151 // Negative width/height means swap.
3152 bool swapSrcX = srcX1 < srcX0;
3153 bool swapSrcY = srcY1 < srcY0;
3154 bool swapDstX = dstX1 < dstX0;
3155 bool swapDstY = dstY1 < dstY0;
3156 int srcW = de::abs(srcX1-srcX0);
3157 int srcH = de::abs(srcY1-srcY0);
3158 int dstW = de::abs(dstX1-dstX0);
3159 int dstH = de::abs(dstY1-dstY0);
3160 bool scale = srcW != dstW || srcH != dstH;
3161 int srcOriginX = swapSrcX ? srcX1 : srcX0;
3162 int srcOriginY = swapSrcY ? srcY1 : srcY0;
3163 int dstOriginX = swapDstX ? dstX1 : dstX0;
3164 int dstOriginY = swapDstY ? dstY1 : dstY0;
3165 IVec4 srcRect = IVec4(srcOriginX, srcOriginY, srcW, srcH);
3166 IVec4 dstRect = IVec4(dstOriginX, dstOriginY, dstW, dstH);
3168 RC_IF_ERROR(filter != GL_NEAREST && filter != GL_LINEAR, GL_INVALID_ENUM, RC_RET_VOID);
3169 RC_IF_ERROR((mask & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0 && filter != GL_NEAREST, GL_INVALID_OPERATION, RC_RET_VOID);
3171 // Validate that both targets are complete.
3172 RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ||
3173 checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_OPERATION, RC_RET_VOID);
3175 // Check samples count is valid
3176 RC_IF_ERROR(getDrawColorbuffer().getNumSamples() != 1, GL_INVALID_OPERATION, RC_RET_VOID);
3178 // Check size restrictions of multisampled case
3179 if (getReadColorbuffer().getNumSamples() != 1)
3181 // Src and Dst rect dimensions must be the same
3182 RC_IF_ERROR(srcW != dstW || srcH != dstH, GL_INVALID_OPERATION, RC_RET_VOID);
3184 // Framebuffer formats must match
3185 if (mask & GL_COLOR_BUFFER_BIT) RC_IF_ERROR(getReadColorbuffer().raw().getFormat() != getDrawColorbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3186 if (mask & GL_DEPTH_BUFFER_BIT) RC_IF_ERROR(getReadDepthbuffer().raw().getFormat() != getDrawDepthbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3187 if (mask & GL_STENCIL_BUFFER_BIT) RC_IF_ERROR(getReadStencilbuffer().raw().getFormat() != getDrawStencilbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3190 // Compute actual source rect.
3191 srcRect = (mask & GL_COLOR_BUFFER_BIT) ? intersect(srcRect, getBufferRect(getReadColorbuffer())) : srcRect;
3192 srcRect = (mask & GL_DEPTH_BUFFER_BIT) ? intersect(srcRect, getBufferRect(getReadDepthbuffer())) : srcRect;
3193 srcRect = (mask & GL_STENCIL_BUFFER_BIT) ? intersect(srcRect, getBufferRect(getReadStencilbuffer())) : srcRect;
3195 // Compute destination rect.
3196 dstRect = (mask & GL_COLOR_BUFFER_BIT) ? intersect(dstRect, getBufferRect(getDrawColorbuffer())) : dstRect;
3197 dstRect = (mask & GL_DEPTH_BUFFER_BIT) ? intersect(dstRect, getBufferRect(getDrawDepthbuffer())) : dstRect;
3198 dstRect = (mask & GL_STENCIL_BUFFER_BIT) ? intersect(dstRect, getBufferRect(getDrawStencilbuffer())) : dstRect;
3199 dstRect = m_scissorEnabled ? intersect(dstRect, m_scissorBox) : dstRect;
3201 if (isEmpty(srcRect) || isEmpty(dstRect))
3202 return; // Don't attempt copy.
3204 // Multisampled read buffer is a special case
3205 if (getReadColorbuffer().getNumSamples() != 1)
3207 deUint32 error = blitResolveMultisampleFramebuffer(mask, srcRect, dstRect, swapSrcX ^ swapDstX, swapSrcY ^ swapDstY);
3209 if (error != GL_NO_ERROR)
3215 // \note Multisample pixel buffers can now be accessed like non-multisampled because multisample read buffer case is already handled. => sample count must be 1
3217 // Coordinate transformation:
3218 // Dst offset space -> dst rectangle space -> src rectangle space -> src offset space.
3219 tcu::Mat3 transform = tcu::translationMatrix(Vec2((float)(srcX0 - srcRect.x()), (float)(srcY0 - srcRect.y())))
3220 * tcu::Mat3(Vec3((float)(srcX1-srcX0) / (float)(dstX1-dstX0),
3221 (float)(srcY1-srcY0) / (float)(dstY1-dstY0),
3223 * tcu::translationMatrix(Vec2((float)(dstRect.x() - dstX0), (float)(dstRect.y() - dstY0)));
3225 if (mask & GL_COLOR_BUFFER_BIT)
3227 tcu::ConstPixelBufferAccess src = tcu::getSubregion(getReadColorbuffer().toSinglesampleAccess(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3228 tcu::PixelBufferAccess dst = tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3229 tcu::TextureChannelClass dstClass = tcu::getTextureChannelClass(dst.getFormat().type);
3230 bool dstIsFloat = dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT ||
3231 dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
3232 dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3233 tcu::Sampler::FilterMode sFilter = (scale && filter == GL_LINEAR) ? tcu::Sampler::LINEAR : tcu::Sampler::NEAREST;
3234 tcu::Sampler sampler (tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
3235 sFilter, sFilter, 0.0f /* lod threshold */, false /* non-normalized coords */);
3236 bool srcIsSRGB = tcu::isSRGB(src.getFormat());
3237 bool dstIsSRGB = tcu::isSRGB(dst.getFormat());
3238 const bool convertSRGB = m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3242 src = tcu::ConstPixelBufferAccess (toNonSRGBFormat(src.getFormat()), src.getWidth(), src.getHeight(), src.getDepth(), src.getRowPitch(), src.getSlicePitch(), src.getDataPtr());
3243 dst = tcu::PixelBufferAccess (toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3246 // \note We don't check for unsupported conversions, unlike spec requires.
3248 for (int yo = 0; yo < dstRect.w(); yo++)
3250 for (int xo = 0; xo < dstRect.z(); xo++)
3252 float dX = (float)xo + 0.5f;
3253 float dY = (float)yo + 0.5f;
3255 // \note Only affine part is used.
3256 float sX = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3257 float sY = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3259 // do not copy pixels outside the modified source region (modified by buffer intersection)
3260 if (sX < 0.0f || sX >= (float)srcRect.z() ||
3261 sY < 0.0f || sY >= (float)srcRect.w())
3264 if (dstIsFloat || srcIsSRGB || filter == tcu::Sampler::LINEAR)
3266 Vec4 p = src.sample2D(sampler, sampler.minFilter, sX, sY, 0);
3267 dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, xo, yo);
3270 dst.setPixel(src.getPixelInt(deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)), xo, yo);
3275 if ((mask & GL_DEPTH_BUFFER_BIT) && m_depthMask)
3277 rr::MultisampleConstPixelBufferAccess src = getDepthMultisampleAccess(rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3278 rr::MultisamplePixelBufferAccess dst = getDepthMultisampleAccess(rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3280 for (int yo = 0; yo < dstRect.w(); yo++)
3282 for (int xo = 0; xo < dstRect.z(); xo++)
3284 const int sampleNdx = 0; // multisample read buffer case is already handled
3286 float dX = (float)xo + 0.5f;
3287 float dY = (float)yo + 0.5f;
3288 float sX = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3289 float sY = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3291 writeDepthOnly(dst, sampleNdx, xo, yo, src.raw().getPixDepth(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)));
3296 if (mask & GL_STENCIL_BUFFER_BIT)
3298 rr::MultisampleConstPixelBufferAccess src = getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3299 rr::MultisamplePixelBufferAccess dst = getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3301 for (int yo = 0; yo < dstRect.w(); yo++)
3303 for (int xo = 0; xo < dstRect.z(); xo++)
3305 const int sampleNdx = 0; // multisample read buffer case is already handled
3307 float dX = (float)xo + 0.5f;
3308 float dY = (float)yo + 0.5f;
3309 float sX = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3310 float sY = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3311 deUint32 srcStencil = src.raw().getPixelUint(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)).x();
3313 writeMaskedStencil(dst, sampleNdx, xo, yo, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3319 void ReferenceContext::invalidateSubFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments, int x, int y, int width, int height)
3321 RC_IF_ERROR(target != GL_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
3322 RC_IF_ERROR((numAttachments < 0) || (numAttachments > 1 && attachments == DE_NULL), GL_INVALID_VALUE, RC_RET_VOID);
3323 RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
3325 // \todo [2012-07-17 pyry] Support multiple color attachments.
3327 const Vec4 colorClearValue (0.0f);
3328 const float depthClearValue = 1.0f;
3329 const int stencilClearValue = 0;
3331 bool isFboBound = m_drawFramebufferBinding != DE_NULL;
3332 bool discardBuffers[3] = { false, false, false }; // Color, depth, stencil
3334 for (int attNdx = 0; attNdx < numAttachments; attNdx++)
3336 bool isColor = attachments[attNdx] == (isFboBound ? GL_COLOR_ATTACHMENT0 : GL_COLOR);
3337 bool isDepth = attachments[attNdx] == (isFboBound ? GL_DEPTH_ATTACHMENT : GL_DEPTH);
3338 bool isStencil = attachments[attNdx] == (isFboBound ? GL_STENCIL_ATTACHMENT : GL_STENCIL);
3339 bool isDepthStencil = isFboBound && attachments[attNdx] == GL_DEPTH_STENCIL_ATTACHMENT;
3341 RC_IF_ERROR(!isColor && !isDepth && !isStencil && !isDepthStencil, GL_INVALID_VALUE, RC_RET_VOID);
3343 if (isColor) discardBuffers[0] = true;
3344 if (isDepth || isDepthStencil) discardBuffers[1] = true;
3345 if (isStencil || isDepthStencil) discardBuffers[2] = true;
3348 for (int ndx = 0; ndx < 3; ndx++)
3350 if (!discardBuffers[ndx])
3353 bool isColor = ndx == 0;
3354 bool isDepth = ndx == 1;
3355 bool isStencil = ndx == 2;
3356 rr::MultisamplePixelBufferAccess buf = isColor ? getDrawColorbuffer() :
3357 isDepth ? getDepthMultisampleAccess(getDrawDepthbuffer()) :
3358 getStencilMultisampleAccess(getDrawStencilbuffer());
3363 tcu::IVec4 area = intersect(tcu::IVec4(0, 0, buf.raw().getHeight(), buf.raw().getDepth()), tcu::IVec4(x, y, width, height));
3364 rr::MultisamplePixelBufferAccess access = rr::getSubregion(buf, area.x(), area.y(), area.z(), area.w());
3367 rr::clear(access, colorClearValue);
3369 rr::clear(access, tcu::Vec4(depthClearValue));
3371 rr::clear(access, tcu::IVec4(stencilClearValue));
3375 void ReferenceContext::invalidateFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments)
3377 // \todo [2012-07-17 pyry] Support multiple color attachments.
3378 rr::MultisampleConstPixelBufferAccess colorBuf0 = getDrawColorbuffer();
3379 rr::MultisampleConstPixelBufferAccess depthBuf = getDrawDepthbuffer();
3380 rr::MultisampleConstPixelBufferAccess stencilBuf = getDrawStencilbuffer();
3384 width = de::max(width, colorBuf0.raw().getHeight());
3385 width = de::max(width, depthBuf.raw().getHeight());
3386 width = de::max(width, stencilBuf.raw().getHeight());
3388 height = de::max(height, colorBuf0.raw().getDepth());
3389 height = de::max(height, depthBuf.raw().getDepth());
3390 height = de::max(height, stencilBuf.raw().getDepth());
3392 invalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, width, height);
3395 void ReferenceContext::clear (deUint32 buffers)
3397 RC_IF_ERROR((buffers & ~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0, GL_INVALID_VALUE, RC_RET_VOID);
3399 rr::MultisamplePixelBufferAccess colorBuf0 = getDrawColorbuffer();
3400 rr::MultisamplePixelBufferAccess depthBuf = getDrawDepthbuffer();
3401 rr::MultisamplePixelBufferAccess stencilBuf = getDrawStencilbuffer();
3402 IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3403 IVec4 colorArea = intersect(baseArea, getBufferRect(colorBuf0));
3404 IVec4 depthArea = intersect(baseArea, getBufferRect(depthBuf));
3405 IVec4 stencilArea = intersect(baseArea, getBufferRect(stencilBuf));
3406 bool hasColor0 = !isEmpty(colorArea);
3407 bool hasDepth = !isEmpty(depthArea);
3408 bool hasStencil = !isEmpty(stencilArea);
3410 if (hasColor0 && (buffers & GL_COLOR_BUFFER_BIT) != 0)
3412 rr::MultisamplePixelBufferAccess access = rr::getSubregion(colorBuf0, colorArea.x(), colorArea.y(), colorArea.z(), colorArea.w());
3413 bool isSRGB = tcu::isSRGB(colorBuf0.raw().getFormat());
3414 Vec4 c = (isSRGB && m_sRGBUpdateEnabled) ? tcu::linearToSRGB(m_clearColor) : m_clearColor;
3415 bool maskUsed = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3416 bool maskZero = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3419 rr::clear(access, c);
3422 for (int y = 0; y < access.raw().getDepth(); y++)
3423 for (int x = 0; x < access.raw().getHeight(); x++)
3424 for (int s = 0; s < access.getNumSamples(); s++)
3425 access.raw().setPixel(tcu::select(c, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3427 // else all channels masked out
3430 if (hasDepth && (buffers & GL_DEPTH_BUFFER_BIT) != 0 && m_depthMask)
3432 rr::MultisamplePixelBufferAccess access = getDepthMultisampleAccess(rr::getSubregion(depthBuf, depthArea.x(), depthArea.y(), depthArea.z(), depthArea.w()));
3433 rr::clearDepth(access, m_clearDepth);
3436 if (hasStencil && (buffers & GL_STENCIL_BUFFER_BIT) != 0)
3438 rr::MultisamplePixelBufferAccess access = getStencilMultisampleAccess(rr::getSubregion(stencilBuf, stencilArea.x(), stencilArea.y(), stencilArea.z(), stencilArea.w()));
3439 int stencilBits = getNumStencilBits(stencilBuf.raw().getFormat());
3440 int stencil = maskStencil(stencilBits, m_clearStencil);
3442 if ((m_stencil[rr::FACETYPE_FRONT].writeMask & ((1u<<stencilBits)-1u)) != ((1u<<stencilBits)-1u))
3444 // Slow path where depth or stencil is masked out in write.
3445 for (int y = 0; y < access.raw().getDepth(); y++)
3446 for (int x = 0; x < access.raw().getHeight(); x++)
3447 for (int s = 0; s < access.getNumSamples(); s++)
3448 writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3451 rr::clearStencil(access, stencil);
3455 void ReferenceContext::clearBufferiv (deUint32 buffer, int drawbuffer, const int* value)
3457 RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3458 RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3460 IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3462 if (buffer == GL_COLOR)
3464 rr::MultisamplePixelBufferAccess colorBuf = getDrawColorbuffer();
3465 bool maskUsed = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3466 bool maskZero = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3467 IVec4 area = intersect(baseArea, getBufferRect(colorBuf));
3469 if (!isEmpty(area) && !maskZero)
3471 rr::MultisamplePixelBufferAccess access = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3472 IVec4 color (value[0], value[1], value[2], value[3]);
3475 rr::clear(access, color);
3478 for (int y = 0; y < access.raw().getDepth(); y++)
3479 for (int x = 0; x < access.raw().getHeight(); x++)
3480 for (int s = 0; s < access.getNumSamples(); s++)
3481 access.raw().setPixel(tcu::select(color, access.raw().getPixelInt(s, x, y), m_colorMask), s, x, y);
3487 TCU_CHECK_INTERNAL(buffer == GL_STENCIL);
3489 rr::MultisamplePixelBufferAccess stencilBuf = getDrawStencilbuffer();
3490 IVec4 area = intersect(baseArea, getBufferRect(stencilBuf));
3492 if (!isEmpty(area) && m_stencil[rr::FACETYPE_FRONT].writeMask != 0)
3494 rr::MultisamplePixelBufferAccess access = getStencilMultisampleAccess(rr::getSubregion(stencilBuf, area.x(), area.y(), area.z(), area.w()));
3495 int stencil = value[0];
3497 for (int y = 0; y < access.raw().getDepth(); y++)
3498 for (int x = 0; x < access.raw().getHeight(); x++)
3499 for (int s = 0; s < access.getNumSamples(); s++)
3500 writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3505 void ReferenceContext::clearBufferfv (deUint32 buffer, int drawbuffer, const float* value)
3507 RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_DEPTH, GL_INVALID_ENUM, RC_RET_VOID);
3508 RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3510 IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3512 if (buffer == GL_COLOR)
3514 rr::MultisamplePixelBufferAccess colorBuf = getDrawColorbuffer();
3515 bool maskUsed = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3516 bool maskZero = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3517 IVec4 area = intersect(baseArea, getBufferRect(colorBuf));
3519 if (!isEmpty(area) && !maskZero)
3521 rr::MultisamplePixelBufferAccess access = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3522 Vec4 color (value[0], value[1], value[2], value[3]);
3524 if (m_sRGBUpdateEnabled && tcu::isSRGB(access.raw().getFormat()))
3525 color = tcu::linearToSRGB(color);
3528 rr::clear(access, color);
3531 for (int y = 0; y < access.raw().getDepth(); y++)
3532 for (int x = 0; x < access.raw().getHeight(); x++)
3533 for (int s = 0; s < access.getNumSamples(); s++)
3534 access.raw().setPixel(tcu::select(color, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3540 TCU_CHECK_INTERNAL(buffer == GL_DEPTH);
3542 rr::MultisamplePixelBufferAccess depthBuf = getDrawDepthbuffer();
3543 IVec4 area = intersect(baseArea, getBufferRect(depthBuf));
3545 if (!isEmpty(area) && m_depthMask)
3547 rr::MultisamplePixelBufferAccess access = rr::getSubregion(depthBuf, area.x(), area.y(), area.z(), area.w());
3548 float depth = value[0];
3550 rr::clearDepth(access, depth);
3555 void ReferenceContext::clearBufferuiv (deUint32 buffer, int drawbuffer, const deUint32* value)
3557 RC_IF_ERROR(buffer != GL_COLOR, GL_INVALID_ENUM, RC_RET_VOID);
3558 RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3560 IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3562 TCU_CHECK_INTERNAL(buffer == GL_COLOR);
3564 rr::MultisamplePixelBufferAccess colorBuf = getDrawColorbuffer();
3565 bool maskUsed = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3566 bool maskZero = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3567 IVec4 area = intersect(baseArea, getBufferRect(colorBuf));
3569 if (!isEmpty(area) && !maskZero)
3571 rr::MultisamplePixelBufferAccess access = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3572 tcu::UVec4 color (value[0], value[1], value[2], value[3]);
3575 rr::clear(access, color.asInt());
3578 for (int y = 0; y < access.raw().getDepth(); y++)
3579 for (int x = 0; x < access.raw().getHeight(); x++)
3580 for (int s = 0; s < access.getNumSamples(); s++)
3581 access.raw().setPixel(tcu::select(color, access.raw().getPixelUint(s, x, y), m_colorMask), s, x, y);
3587 void ReferenceContext::clearBufferfi (deUint32 buffer, int drawbuffer, float depth, int stencil)
3589 RC_IF_ERROR(buffer != GL_DEPTH_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3590 clearBufferfv(GL_DEPTH, drawbuffer, &depth);
3591 clearBufferiv(GL_STENCIL, drawbuffer, &stencil);
3594 void ReferenceContext::bindVertexArray (deUint32 array)
3596 rc::VertexArray* vertexArrayObject = DE_NULL;
3600 vertexArrayObject = m_vertexArrays.find(array);
3601 if (!vertexArrayObject)
3603 vertexArrayObject = new rc::VertexArray(array, m_limits.maxVertexAttribs);
3604 m_vertexArrays.insert(vertexArrayObject);
3608 // Create new references
3609 if (vertexArrayObject)
3610 m_vertexArrays.acquireReference(vertexArrayObject);
3612 // Remove old references
3613 if (m_vertexArrayBinding)
3614 m_vertexArrays.releaseReference(m_vertexArrayBinding);
3616 m_vertexArrayBinding = vertexArrayObject;
3619 void ReferenceContext::genVertexArrays (int numArrays, deUint32* vertexArrays)
3621 RC_IF_ERROR(!vertexArrays, GL_INVALID_VALUE, RC_RET_VOID);
3623 for (int ndx = 0; ndx < numArrays; ndx++)
3624 vertexArrays[ndx] = m_vertexArrays.allocateName();
3627 void ReferenceContext::deleteVertexArrays (int numArrays, const deUint32* vertexArrays)
3629 for (int i = 0; i < numArrays; i++)
3631 deUint32 name = vertexArrays[i];
3632 VertexArray* vertexArray = name ? m_vertexArrays.find(name) : DE_NULL;
3635 deleteVertexArray(vertexArray);
3639 void ReferenceContext::vertexAttribPointer (deUint32 index, int rawSize, deUint32 type, deBool normalized, int stride, const void *pointer)
3641 const bool allowBGRA = !glu::isContextTypeES(getType());
3642 const int effectiveSize = (allowBGRA && rawSize == GL_BGRA) ? (4) : (rawSize);
3644 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3645 RC_IF_ERROR(effectiveSize <= 0 || effectiveSize > 4, GL_INVALID_VALUE, RC_RET_VOID);
3646 RC_IF_ERROR(type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
3647 type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
3648 type != GL_INT && type != GL_UNSIGNED_INT &&
3649 type != GL_FIXED && type != GL_DOUBLE &&
3650 type != GL_FLOAT && type != GL_HALF_FLOAT &&
3651 type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_INT_2_10_10_10_REV, GL_INVALID_ENUM, RC_RET_VOID);
3652 RC_IF_ERROR(normalized != GL_TRUE && normalized != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3653 RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3654 RC_IF_ERROR((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && effectiveSize != 4, GL_INVALID_OPERATION, RC_RET_VOID);
3655 RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3656 RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_INT_2_10_10_10_REV && type != GL_UNSIGNED_BYTE, GL_INVALID_OPERATION, RC_RET_VOID);
3657 RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && normalized == GL_FALSE, GL_INVALID_OPERATION, RC_RET_VOID);
3659 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3661 vao.m_arrays[index].size = rawSize;
3662 vao.m_arrays[index].stride = stride;
3663 vao.m_arrays[index].type = type;
3664 vao.m_arrays[index].normalized = normalized == GL_TRUE;
3665 vao.m_arrays[index].integer = false;
3666 vao.m_arrays[index].pointer = pointer;
3668 // acquire new reference
3669 if (m_arrayBufferBinding)
3670 m_buffers.acquireReference(m_arrayBufferBinding);
3672 // release old reference
3673 if (vao.m_arrays[index].bufferBinding)
3674 m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3676 vao.m_arrays[index].bufferDeleted = false;
3677 vao.m_arrays[index].bufferBinding = m_arrayBufferBinding;
3680 void ReferenceContext::vertexAttribIPointer (deUint32 index, int size, deUint32 type, int stride, const void *pointer)
3682 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3683 RC_IF_ERROR(size <= 0 || size > 4, GL_INVALID_VALUE, RC_RET_VOID);
3684 RC_IF_ERROR(type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
3685 type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
3686 type != GL_INT && type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
3687 RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3688 RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3690 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3692 vao.m_arrays[index].size = size;
3693 vao.m_arrays[index].stride = stride;
3694 vao.m_arrays[index].type = type;
3695 vao.m_arrays[index].normalized = false;
3696 vao.m_arrays[index].integer = true;
3697 vao.m_arrays[index].pointer = pointer;
3699 // acquire new reference
3700 if (m_arrayBufferBinding)
3701 m_buffers.acquireReference(m_arrayBufferBinding);
3703 // release old reference
3704 if (vao.m_arrays[index].bufferBinding)
3705 m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3707 vao.m_arrays[index].bufferDeleted = false;
3708 vao.m_arrays[index].bufferBinding = m_arrayBufferBinding;
3711 void ReferenceContext::enableVertexAttribArray (deUint32 index)
3713 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3715 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3716 vao.m_arrays[index].enabled = true;
3719 void ReferenceContext::disableVertexAttribArray (deUint32 index)
3721 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3723 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3724 vao.m_arrays[index].enabled = false;
3727 void ReferenceContext::vertexAttribDivisor (deUint32 index, deUint32 divisor)
3729 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3731 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3732 vao.m_arrays[index].divisor = divisor;
3735 void ReferenceContext::vertexAttrib1f (deUint32 index, float x)
3737 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3739 m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, 0, 0, 1));
3742 void ReferenceContext::vertexAttrib2f (deUint32 index, float x, float y)
3744 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3746 m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, 0, 1));
3749 void ReferenceContext::vertexAttrib3f (deUint32 index, float x, float y, float z)
3751 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3753 m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, 1));
3756 void ReferenceContext::vertexAttrib4f (deUint32 index, float x, float y, float z, float w)
3758 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3760 m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, w));
3763 void ReferenceContext::vertexAttribI4i (deUint32 index, deInt32 x, deInt32 y, deInt32 z, deInt32 w)
3765 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3767 m_currentAttribs[index] = rr::GenericVec4(tcu::IVec4(x, y, z, w));
3770 void ReferenceContext::vertexAttribI4ui (deUint32 index, deUint32 x, deUint32 y, deUint32 z, deUint32 w)
3772 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3774 m_currentAttribs[index] = rr::GenericVec4(tcu::UVec4(x, y, z, w));
3777 deInt32 ReferenceContext::getAttribLocation (deUint32 program, const char *name)
3779 ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3781 RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3785 std::string nameString(name);
3787 for (size_t ndx = 0; ndx < shaderProg->m_program->m_attributeNames.size(); ++ndx)
3788 if (shaderProg->m_program->m_attributeNames[ndx] == nameString)
3795 void ReferenceContext::uniformv (deInt32 location, glu::DataType type, deInt32 count, const void* v)
3797 RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3799 std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3804 RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3805 RC_IF_ERROR(uniforms[location].type != type, GL_INVALID_OPERATION, RC_RET_VOID);
3806 RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3809 const int scalarSize = glu::getDataTypeScalarSize(type);
3810 DE_ASSERT(scalarSize*sizeof(deUint32) <= sizeof(uniforms[location].value));
3811 deMemcpy(&uniforms[location].value, v, scalarSize*(int)sizeof(deUint32));
3815 void ReferenceContext::uniform1iv (deInt32 location, deInt32 count, const deInt32* v)
3817 RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3819 std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3824 RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3825 RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3827 switch (uniforms[location].type)
3829 case glu::TYPE_INT: uniforms[location].value.i = *v; return;
3831 // \note texture unit is stored to value
3832 case glu::TYPE_SAMPLER_2D:
3833 case glu::TYPE_UINT_SAMPLER_2D:
3834 case glu::TYPE_INT_SAMPLER_2D:
3835 case glu::TYPE_SAMPLER_CUBE:
3836 case glu::TYPE_UINT_SAMPLER_CUBE:
3837 case glu::TYPE_INT_SAMPLER_CUBE:
3838 case glu::TYPE_SAMPLER_2D_ARRAY:
3839 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
3840 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
3841 case glu::TYPE_SAMPLER_3D:
3842 case glu::TYPE_UINT_SAMPLER_3D:
3843 case glu::TYPE_INT_SAMPLER_3D:
3844 case glu::TYPE_SAMPLER_CUBE_ARRAY:
3845 case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
3846 case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
3847 uniforms[location].value.i = *v;
3851 setError(GL_INVALID_OPERATION);
3856 void ReferenceContext::uniform1f (deInt32 location, const float v0)
3858 uniform1fv(location, 1, &v0);
3861 void ReferenceContext::uniform1i (deInt32 location, deInt32 v0)
3863 uniform1iv(location, 1, &v0);
3866 void ReferenceContext::uniform1fv (deInt32 location, deInt32 count, const float* v)
3868 uniformv(location, glu::TYPE_FLOAT, count, v);
3871 void ReferenceContext::uniform2fv (deInt32 location, deInt32 count, const float* v)
3873 uniformv(location, glu::TYPE_FLOAT_VEC2, count, v);
3876 void ReferenceContext::uniform3fv (deInt32 location, deInt32 count, const float* v)
3878 uniformv(location, glu::TYPE_FLOAT_VEC3, count, v);
3881 void ReferenceContext::uniform4fv (deInt32 location, deInt32 count, const float* v)
3883 uniformv(location, glu::TYPE_FLOAT_VEC4, count, v);
3886 void ReferenceContext::uniform2iv (deInt32 location, deInt32 count, const deInt32* v)
3888 uniformv(location, glu::TYPE_INT_VEC2, count, v);
3891 void ReferenceContext::uniform3iv (deInt32 location, deInt32 count, const deInt32* v)
3893 uniformv(location, glu::TYPE_INT_VEC3, count, v);
3896 void ReferenceContext::uniform4iv (deInt32 location, deInt32 count, const deInt32* v)
3898 uniformv(location, glu::TYPE_INT_VEC4, count, v);
3901 void ReferenceContext::uniformMatrix3fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
3903 RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3905 std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3910 RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3915 RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3917 switch (uniforms[location].type)
3919 case glu::TYPE_FLOAT_MAT3:
3920 RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3922 if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3923 for (int row = 0; row < 3; ++row)
3924 for (int col = 0; col < 3; ++col)
3925 uniforms[location].value.m3[row*3+col] = value[col*3+row];
3926 else // input is row major
3927 for (int row = 0; row < 3; ++row)
3928 for (int col = 0; col < 3; ++col)
3929 uniforms[location].value.m3[row*3+col] = value[row*3+col];
3934 setError(GL_INVALID_OPERATION);
3939 void ReferenceContext::uniformMatrix4fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
3941 RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3943 std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3948 RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3953 RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3955 switch (uniforms[location].type)
3957 case glu::TYPE_FLOAT_MAT4:
3958 RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3960 if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3961 for (int row = 0; row < 4; ++row)
3962 for (int col = 0; col < 4; ++col)
3963 uniforms[location].value.m4[row*3+col] = value[col*3+row];
3964 else // input is row major
3965 for (int row = 0; row < 4; ++row)
3966 for (int col = 0; col < 4; ++col)
3967 uniforms[location].value.m4[row*3+col] = value[row*3+col];
3972 setError(GL_INVALID_OPERATION);
3977 deInt32 ReferenceContext::getUniformLocation (deUint32 program, const char *name)
3979 ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3980 RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3982 std::vector<sglr::UniformSlot>& uniforms = shaderProg->m_program->m_uniforms;
3984 for (size_t i = 0; i < uniforms.size(); ++i)
3985 if (name && deStringEqual(uniforms[i].name.c_str(), name))
3991 void ReferenceContext::lineWidth (float w)
3993 RC_IF_ERROR(w < 0.0f, GL_INVALID_VALUE, RC_RET_VOID);
3997 void ReferenceContext::deleteVertexArray (rc::VertexArray* vertexArray)
3999 if (m_vertexArrayBinding == vertexArray)
4002 if (vertexArray->m_elementArrayBufferBinding)
4003 m_buffers.releaseReference(vertexArray->m_elementArrayBufferBinding);
4005 for (size_t ndx = 0; ndx < vertexArray->m_arrays.size(); ++ndx)
4006 if (vertexArray->m_arrays[ndx].bufferBinding)
4007 m_buffers.releaseReference(vertexArray->m_arrays[ndx].bufferBinding);
4009 DE_ASSERT(vertexArray->getRefCount() == 1);
4010 m_vertexArrays.releaseReference(vertexArray);
4013 void ReferenceContext::deleteProgramObject (rc::ShaderProgramObjectContainer* sp)
4015 // Unbinding program will delete it
4016 if (m_currentProgram == sp && sp->m_deleteFlag)
4022 // Unbinding program will NOT delete it
4023 if (m_currentProgram == sp)
4026 DE_ASSERT(sp->getRefCount() == 1);
4027 m_programs.releaseReference(sp);
4030 void ReferenceContext::drawArrays (deUint32 mode, int first, int count)
4032 drawArraysInstanced(mode, first, count, 1);
4035 void ReferenceContext::drawArraysInstanced (deUint32 mode, int first, int count, int instanceCount)
4039 RC_IF_ERROR(first < 0 || count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4041 if (!predrawErrorChecks(mode))
4047 const rr::PrimitiveType primitiveType = sglr::rr_util::mapGLPrimitiveType(mode);
4049 drawWithReference(rr::PrimitiveList(primitiveType, count, first), instanceCount);
4053 void ReferenceContext::drawElements (deUint32 mode, int count, deUint32 type, const void *indices)
4055 drawElementsInstanced(mode, count, type, indices, 1);
4058 void ReferenceContext::drawElementsBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int baseVertex)
4060 drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex);
4063 void ReferenceContext::drawElementsInstanced (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount)
4065 drawElementsInstancedBaseVertex(mode, count, type, indices, instanceCount, 0);
4068 void ReferenceContext::drawElementsInstancedBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount, int baseVertex)
4070 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4074 RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4075 type != GL_UNSIGNED_SHORT &&
4076 type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4077 RC_IF_ERROR(count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4079 if (!predrawErrorChecks(mode))
4085 const rr::PrimitiveType primitiveType = sglr::rr_util::mapGLPrimitiveType(mode);
4086 const void* indicesPtr = (vao.m_elementArrayBufferBinding) ? (vao.m_elementArrayBufferBinding->getData() + reinterpret_cast<uintptr_t>(indices)) : (indices);
4088 drawWithReference(rr::PrimitiveList(primitiveType, count, rr::DrawIndices(indicesPtr, sglr::rr_util::mapGLIndexType(type), baseVertex)), instanceCount);
4092 void ReferenceContext::drawRangeElements (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices)
4094 RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4096 drawElements(mode, count, type, indices);
4099 void ReferenceContext::drawRangeElementsBaseVertex (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices, int baseVertex)
4101 RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4103 drawElementsBaseVertex(mode, count, type, indices, baseVertex);
4106 void ReferenceContext::drawArraysIndirect (deUint32 mode, const void *indirect)
4108 struct DrawArraysIndirectCommand
4113 deUint32 reservedMustBeZero;
4116 const DrawArraysIndirectCommand* command;
4120 if (!predrawErrorChecks(mode))
4123 // Check pointer validity
4125 RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4126 RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4128 // \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4129 RC_IF_ERROR((size_t)reinterpret_cast<uintptr_t>(indirect) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4130 RC_IF_ERROR((size_t)reinterpret_cast<uintptr_t>(indirect) + sizeof(DrawArraysIndirectCommand) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4134 command = (const DrawArraysIndirectCommand*)(m_drawIndirectBufferBinding->getData() + reinterpret_cast<uintptr_t>(indirect));
4135 RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4138 drawArraysInstanced(mode, command->first, command->count, command->primCount);
4141 void ReferenceContext::drawElementsIndirect (deUint32 mode, deUint32 type, const void *indirect)
4143 struct DrawElementsIndirectCommand
4147 deUint32 firstIndex;
4149 deUint32 reservedMustBeZero;
4152 const DrawElementsIndirectCommand* command;
4156 if (!predrawErrorChecks(mode))
4159 RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4160 type != GL_UNSIGNED_SHORT &&
4161 type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4163 RC_IF_ERROR(!getBufferBinding(GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_OPERATION, RC_RET_VOID);
4165 // Check pointer validity
4167 RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4168 RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4170 // \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4171 RC_IF_ERROR((size_t)reinterpret_cast<uintptr_t>(indirect) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4172 RC_IF_ERROR((size_t)reinterpret_cast<uintptr_t>(indirect) + sizeof(DrawElementsIndirectCommand) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4176 command = (const DrawElementsIndirectCommand*)(m_drawIndirectBufferBinding->getData() + reinterpret_cast<uintptr_t>(indirect));
4177 RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4179 // Check command error conditions
4180 RC_IF_ERROR((int)command->count < 0 || (int)command->primCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4184 const size_t sizeOfType = (type == GL_UNSIGNED_BYTE) ? (1) : ((type == GL_UNSIGNED_SHORT) ? (2) : (4));
4185 const void* indicesPtr = glu::BufferOffsetAsPointer(command->firstIndex * sizeOfType);
4187 drawElementsInstancedBaseVertex(mode, (int)command->count, type, indicesPtr, (int)command->primCount, command->baseVertex);
4191 void ReferenceContext::multiDrawArrays (deUint32 mode, const int* first, const int* count, int primCount)
4196 DE_UNREF(primCount);
4198 // not supported in gles, prevent accidental use
4202 void ReferenceContext::multiDrawElements (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount)
4208 DE_UNREF(primCount);
4210 // not supported in gles, prevent accidental use
4214 void ReferenceContext::multiDrawElementsBaseVertex (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount, const int* baseVertex)
4220 DE_UNREF(primCount);
4221 DE_UNREF(baseVertex);
4223 // not supported in gles, prevent accidental use
4227 bool ReferenceContext::predrawErrorChecks (deUint32 mode)
4229 RC_IF_ERROR(mode != GL_POINTS &&
4230 mode != GL_LINE_STRIP && mode != GL_LINE_LOOP && mode != GL_LINES &&
4231 mode != GL_TRIANGLE_STRIP && mode != GL_TRIANGLE_FAN && mode != GL_TRIANGLES &&
4232 mode != GL_LINES_ADJACENCY && mode != GL_LINE_STRIP_ADJACENCY &&
4233 mode != GL_TRIANGLES_ADJACENCY && mode != GL_TRIANGLE_STRIP_ADJACENCY,
4234 GL_INVALID_ENUM, false);
4236 // \todo [jarkko] Uncomment following code when the buffer mapping support is added
4237 //for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4238 // if (vao.m_arrays[ndx].enabled && vao.m_arrays[ndx].bufferBinding && vao.m_arrays[ndx].bufferBinding->isMapped)
4239 // RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4241 RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION, false);
4243 // Geometry shader checks
4244 if (m_currentProgram && m_currentProgram->m_program->m_hasGeometryShader)
4246 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS && mode != GL_POINTS, GL_INVALID_OPERATION, false);
4248 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
4249 (mode != GL_LINES &&
4250 mode != GL_LINE_STRIP &&
4251 mode != GL_LINE_LOOP),
4252 GL_INVALID_OPERATION, false);
4254 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
4255 (mode != GL_TRIANGLES &&
4256 mode != GL_TRIANGLE_STRIP &&
4257 mode != GL_TRIANGLE_FAN),
4258 GL_INVALID_OPERATION, false);
4260 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
4261 (mode != GL_LINES_ADJACENCY &&
4262 mode != GL_LINE_STRIP_ADJACENCY),
4263 GL_INVALID_OPERATION, false);
4265 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
4266 (mode != GL_TRIANGLES_ADJACENCY &&
4267 mode != GL_TRIANGLE_STRIP_ADJACENCY),
4268 GL_INVALID_OPERATION, false);
4274 static rr::PrimitiveType getPrimitiveBaseType (rr::PrimitiveType derivedType)
4276 switch (derivedType)
4278 case rr::PRIMITIVETYPE_TRIANGLES:
4279 case rr::PRIMITIVETYPE_TRIANGLE_STRIP:
4280 case rr::PRIMITIVETYPE_TRIANGLE_FAN:
4281 case rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY:
4282 case rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:
4283 return rr::PRIMITIVETYPE_TRIANGLES;
4285 case rr::PRIMITIVETYPE_LINES:
4286 case rr::PRIMITIVETYPE_LINE_STRIP:
4287 case rr::PRIMITIVETYPE_LINE_LOOP:
4288 case rr::PRIMITIVETYPE_LINES_ADJACENCY:
4289 case rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY:
4290 return rr::PRIMITIVETYPE_LINES;
4292 case rr::PRIMITIVETYPE_POINTS:
4293 return rr::PRIMITIVETYPE_POINTS;
4297 return rr::PRIMITIVETYPE_LAST;
4301 static deUint32 getFixedRestartIndex (rr::IndexType indexType)
4305 case rr::INDEXTYPE_UINT8: return 0xFF;
4306 case rr::INDEXTYPE_UINT16: return 0xFFFF;
4307 case rr::INDEXTYPE_UINT32: return 0xFFFFFFFFul;
4309 case rr::INDEXTYPE_LAST:
4316 void ReferenceContext::drawWithReference (const rr::PrimitiveList& primitives, int instanceCount)
4318 // undefined results
4319 if (m_currentProgram == DE_NULL)
4322 rr::MultisamplePixelBufferAccess colorBuf0 = getDrawColorbuffer();
4323 rr::MultisamplePixelBufferAccess depthBuf = getDepthMultisampleAccess(getDrawDepthbuffer());
4324 rr::MultisamplePixelBufferAccess stencilBuf = getStencilMultisampleAccess(getDrawStencilbuffer());
4325 const bool hasStencil = !isEmpty(stencilBuf);
4326 const int stencilBits = (hasStencil) ? (getNumStencilBits(stencilBuf.raw().getFormat())) : (0);
4328 const rr::RenderTarget renderTarget(colorBuf0, depthBuf, stencilBuf);
4329 const rr::Program program (m_currentProgram->m_program->getVertexShader(),
4330 m_currentProgram->m_program->getFragmentShader(),
4331 (m_currentProgram->m_program->m_hasGeometryShader) ? (m_currentProgram->m_program->getGeometryShader()) : (DE_NULL));
4332 rr::RenderState state ((rr::ViewportState)(colorBuf0), m_limits.subpixelBits);
4334 const rr::Renderer referenceRenderer;
4335 std::vector<rr::VertexAttrib> vertexAttribs;
4339 const rr::PrimitiveType baseType = getPrimitiveBaseType(primitives.getPrimitiveType());
4340 const bool polygonOffsetEnabled = (baseType == rr::PRIMITIVETYPE_TRIANGLES) ? (m_polygonOffsetFillEnabled) : (false);
4342 //state.cullMode = m_cullMode
4344 state.fragOps.scissorTestEnabled = m_scissorEnabled;
4345 state.fragOps.scissorRectangle = rr::WindowRectangle(m_scissorBox.x(), m_scissorBox.y(), m_scissorBox.z(), m_scissorBox.w());
4347 state.fragOps.numStencilBits = stencilBits;
4348 state.fragOps.stencilTestEnabled = m_stencilTestEnabled;
4350 for (int faceType = 0; faceType < rr::FACETYPE_LAST; faceType++)
4352 state.fragOps.stencilStates[faceType].compMask = m_stencil[faceType].opMask;
4353 state.fragOps.stencilStates[faceType].writeMask = m_stencil[faceType].writeMask;
4354 state.fragOps.stencilStates[faceType].ref = m_stencil[faceType].ref;
4355 state.fragOps.stencilStates[faceType].func = sglr::rr_util::mapGLTestFunc(m_stencil[faceType].func);
4356 state.fragOps.stencilStates[faceType].sFail = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opStencilFail);
4357 state.fragOps.stencilStates[faceType].dpFail = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthFail);
4358 state.fragOps.stencilStates[faceType].dpPass = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthPass);
4361 state.fragOps.depthTestEnabled = m_depthTestEnabled;
4362 state.fragOps.depthFunc = sglr::rr_util::mapGLTestFunc(m_depthFunc);
4363 state.fragOps.depthMask = m_depthMask;
4365 state.fragOps.blendMode = m_blendEnabled ? rr::BLENDMODE_STANDARD : rr::BLENDMODE_NONE;
4366 state.fragOps.blendRGBState.equation = sglr::rr_util::mapGLBlendEquation(m_blendModeRGB);
4367 state.fragOps.blendRGBState.srcFunc = sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcRGB);
4368 state.fragOps.blendRGBState.dstFunc = sglr::rr_util::mapGLBlendFunc(m_blendFactorDstRGB);
4369 state.fragOps.blendAState.equation = sglr::rr_util::mapGLBlendEquation(m_blendModeAlpha);
4370 state.fragOps.blendAState.srcFunc = sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcAlpha);
4371 state.fragOps.blendAState.dstFunc = sglr::rr_util::mapGLBlendFunc(m_blendFactorDstAlpha);
4372 state.fragOps.blendColor = m_blendColor;
4374 state.fragOps.sRGBEnabled = m_sRGBUpdateEnabled;
4376 state.fragOps.colorMask = m_colorMask;
4378 state.fragOps.depthClampEnabled = m_depthClampEnabled;
4380 state.viewport.rect = rr::WindowRectangle(m_viewport.x(), m_viewport.y(), m_viewport.z(), m_viewport.w());
4381 state.viewport.zn = m_depthRangeNear;
4382 state.viewport.zf = m_depthRangeFar;
4384 //state.point.pointSize = m_pointSize;
4385 state.line.lineWidth = m_lineWidth;
4387 state.fragOps.polygonOffsetEnabled = polygonOffsetEnabled;
4388 state.fragOps.polygonOffsetFactor = m_polygonOffsetFactor;
4389 state.fragOps.polygonOffsetUnits = m_polygonOffsetUnits;
4392 const rr::IndexType indexType = primitives.getIndexType();
4394 if (m_primitiveRestartFixedIndex && indexType != rr::INDEXTYPE_LAST)
4396 state.restart.enabled = true;
4397 state.restart.restartIndex = getFixedRestartIndex(indexType);
4399 else if (m_primitiveRestartSettableIndex)
4401 // \note PRIMITIVE_RESTART is active for non-indexed (DrawArrays) operations too.
4402 state.restart.enabled = true;
4403 state.restart.restartIndex = m_primitiveRestartIndex;
4407 state.restart.enabled = false;
4411 state.provokingVertexConvention = (m_provokingFirstVertexConvention) ? (rr::PROVOKINGVERTEX_FIRST) : (rr::PROVOKINGVERTEX_LAST);
4416 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4418 vertexAttribs.resize(vao.m_arrays.size());
4419 for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4421 if (!vao.m_arrays[ndx].enabled)
4423 vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading with wrong type is allowed, but results are undefined
4424 vertexAttribs[ndx].generic = m_currentAttribs[ndx];
4426 else if (vao.m_arrays[ndx].bufferDeleted)
4428 vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading from deleted buffer, output zeros
4429 vertexAttribs[ndx].generic = tcu::Vec4(0, 0, 0, 0);
4433 vertexAttribs[ndx].type = (vao.m_arrays[ndx].integer) ?
4434 (sglr::rr_util::mapGLPureIntegerVertexAttributeType(vao.m_arrays[ndx].type)) :
4435 (sglr::rr_util::mapGLFloatVertexAttributeType(vao.m_arrays[ndx].type, vao.m_arrays[ndx].normalized, vao.m_arrays[ndx].size, this->getType()));
4436 vertexAttribs[ndx].size = sglr::rr_util::mapGLSize(vao.m_arrays[ndx].size);
4437 vertexAttribs[ndx].stride = vao.m_arrays[ndx].stride;
4438 vertexAttribs[ndx].instanceDivisor = vao.m_arrays[ndx].divisor;
4439 vertexAttribs[ndx].pointer = (vao.m_arrays[ndx].bufferBinding) ? (vao.m_arrays[ndx].bufferBinding->getData() + reinterpret_cast<uintptr_t>(vao.m_arrays[ndx].pointer)) : (vao.m_arrays[ndx].pointer);
4444 // Set shader samplers
4445 for (size_t uniformNdx = 0; uniformNdx < m_currentProgram->m_program->m_uniforms.size(); ++uniformNdx)
4447 const tcu::Sampler::DepthStencilMode depthStencilMode = tcu::Sampler::MODE_DEPTH; // \todo[jarkko] support sampler state
4448 const int texNdx = m_currentProgram->m_program->m_uniforms[uniformNdx].value.i;
4450 switch (m_currentProgram->m_program->m_uniforms[uniformNdx].type)
4452 case glu::TYPE_SAMPLER_1D:
4453 case glu::TYPE_UINT_SAMPLER_1D:
4454 case glu::TYPE_INT_SAMPLER_1D:
4456 rc::Texture1D* tex = DE_NULL;
4458 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4459 tex = (m_textureUnits[texNdx].tex1DBinding) ? (m_textureUnits[texNdx].tex1DBinding) : (&m_textureUnits[texNdx].default1DTex);
4461 if (tex && tex->isComplete())
4463 tex->updateView(depthStencilMode);
4464 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = tex;
4467 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = &m_emptyTex1D;
4471 case glu::TYPE_SAMPLER_2D:
4472 case glu::TYPE_UINT_SAMPLER_2D:
4473 case glu::TYPE_INT_SAMPLER_2D:
4475 rc::Texture2D* tex = DE_NULL;
4477 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4478 tex = (m_textureUnits[texNdx].tex2DBinding) ? (m_textureUnits[texNdx].tex2DBinding) : (&m_textureUnits[texNdx].default2DTex);
4480 if (tex && tex->isComplete())
4482 tex->updateView(depthStencilMode);
4483 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = tex;
4486 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = &m_emptyTex2D;
4490 case glu::TYPE_SAMPLER_CUBE:
4491 case glu::TYPE_UINT_SAMPLER_CUBE:
4492 case glu::TYPE_INT_SAMPLER_CUBE:
4494 rc::TextureCube* tex = DE_NULL;
4496 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4497 tex = (m_textureUnits[texNdx].texCubeBinding) ? (m_textureUnits[texNdx].texCubeBinding) : (&m_textureUnits[texNdx].defaultCubeTex);
4499 if (tex && tex->isComplete())
4501 tex->updateView(depthStencilMode);
4502 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = tex;
4505 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = &m_emptyTexCube;
4509 case glu::TYPE_SAMPLER_2D_ARRAY:
4510 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
4511 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
4513 rc::Texture2DArray* tex = DE_NULL;
4515 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4516 tex = (m_textureUnits[texNdx].tex2DArrayBinding) ? (m_textureUnits[texNdx].tex2DArrayBinding) : (&m_textureUnits[texNdx].default2DArrayTex);
4518 if (tex && tex->isComplete())
4520 tex->updateView(depthStencilMode);
4521 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = tex;
4524 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = &m_emptyTex2DArray;
4528 case glu::TYPE_SAMPLER_3D:
4529 case glu::TYPE_UINT_SAMPLER_3D:
4530 case glu::TYPE_INT_SAMPLER_3D:
4532 rc::Texture3D* tex = DE_NULL;
4534 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4535 tex = (m_textureUnits[texNdx].tex3DBinding) ? (m_textureUnits[texNdx].tex3DBinding) : (&m_textureUnits[texNdx].default3DTex);
4537 if (tex && tex->isComplete())
4539 tex->updateView(depthStencilMode);
4540 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = tex;
4543 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = &m_emptyTex3D;
4547 case glu::TYPE_SAMPLER_CUBE_ARRAY:
4548 case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
4549 case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
4551 rc::TextureCubeArray* tex = DE_NULL;
4553 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4554 tex = (m_textureUnits[texNdx].texCubeArrayBinding) ? (m_textureUnits[texNdx].texCubeArrayBinding) : (&m_textureUnits[texNdx].defaultCubeArrayTex);
4556 if (tex && tex->isComplete())
4558 tex->updateView(depthStencilMode);
4559 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = tex;
4562 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = &m_emptyTexCubeArray;
4572 referenceRenderer.drawInstanced(rr::DrawCommand(state, renderTarget, program, (int)vertexAttribs.size(), &vertexAttribs[0], primitives), instanceCount);
4575 deUint32 ReferenceContext::createProgram (ShaderProgram* program)
4577 int name = m_programs.allocateName();
4579 m_programs.insert(new rc::ShaderProgramObjectContainer(name, program));
4584 void ReferenceContext::useProgram (deUint32 program)
4586 rc::ShaderProgramObjectContainer* shaderProg = DE_NULL;
4587 rc::ShaderProgramObjectContainer* programToBeDeleted = DE_NULL;
4591 shaderProg = m_programs.find(program);
4593 // shader has not been linked
4594 if (!shaderProg || shaderProg->m_deleteFlag)
4595 RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4598 if (m_currentProgram && m_currentProgram->m_deleteFlag)
4599 programToBeDeleted = m_currentProgram;
4601 m_currentProgram = shaderProg;
4603 if (programToBeDeleted)
4605 DE_ASSERT(programToBeDeleted->getRefCount() == 1);
4606 deleteProgramObject(programToBeDeleted);
4610 void ReferenceContext::deleteProgram (deUint32 program)
4615 rc::ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
4618 if (shaderProg == m_currentProgram)
4620 m_currentProgram->m_deleteFlag = true;
4624 DE_ASSERT(shaderProg->getRefCount() == 1);
4625 m_programs.releaseReference(shaderProg);
4630 void ReferenceContext::readPixels (int x, int y, int width, int height, deUint32 format, deUint32 type, void* data)
4632 rr::MultisamplePixelBufferAccess src = getReadColorbuffer();
4633 TextureFormat transferFmt;
4635 // Map transfer format.
4636 transferFmt = glu::mapGLTransferFormat(format, type);
4637 RC_IF_ERROR(transferFmt.order == TextureFormat::CHANNELORDER_LAST ||
4638 transferFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
4640 // Clamp input values
4641 const int copyX = deClamp32(x, 0, src.raw().getHeight());
4642 const int copyY = deClamp32(y, 0, src.raw().getDepth());
4643 const int copyWidth = deClamp32(width, 0, src.raw().getHeight()-x);
4644 const int copyHeight = deClamp32(height, 0, src.raw().getDepth()-y);
4646 PixelBufferAccess dst(transferFmt, width, height, 1, deAlign32(width*transferFmt.getPixelSize(), m_pixelPackAlignment), 0, getPixelPackPtr(data));
4647 rr::resolveMultisampleColorBuffer(tcu::getSubregion(dst, 0, 0, copyWidth, copyHeight), rr::getSubregion(src, copyX, copyY, copyWidth, copyHeight));
4650 deUint32 ReferenceContext::getError (void)
4652 deUint32 err = m_lastError;
4653 m_lastError = GL_NO_ERROR;
4657 void ReferenceContext::finish (void)
4661 inline void ReferenceContext::setError (deUint32 error)
4663 if (m_lastError == GL_NO_ERROR)
4664 m_lastError = error;
4667 void ReferenceContext::getIntegerv (deUint32 pname, int* param)
4671 case GL_MAX_TEXTURE_SIZE: *param = m_limits.maxTexture2DSize; break;
4672 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *param = m_limits.maxTextureCubeSize; break;
4673 case GL_MAX_ARRAY_TEXTURE_LAYERS: *param = m_limits.maxTexture2DArrayLayers; break;
4674 case GL_MAX_3D_TEXTURE_SIZE: *param = m_limits.maxTexture3DSize; break;
4675 case GL_MAX_RENDERBUFFER_SIZE: *param = m_limits.maxRenderbufferSize; break;
4676 case GL_MAX_TEXTURE_IMAGE_UNITS: *param = m_limits.maxTextureImageUnits; break;
4677 case GL_MAX_VERTEX_ATTRIBS: *param = m_limits.maxVertexAttribs; break;
4680 setError(GL_INVALID_ENUM);
4685 const char* ReferenceContext::getString (deUint32 pname)
4689 case GL_EXTENSIONS: return m_limits.extensionStr.c_str();
4692 setError(GL_INVALID_ENUM);
4700 TextureLevelArray::TextureLevelArray (void)
4704 TextureLevelArray::~TextureLevelArray (void)
4709 void TextureLevelArray::clear (void)
4711 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_data) == DE_LENGTH_OF_ARRAY(m_access));
4713 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(m_data); ndx++)
4715 m_data[ndx].clear();
4716 m_access[ndx] = PixelBufferAccess();
4720 void TextureLevelArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
4722 const int dataSize = format.getPixelSize()*width*height*depth;
4724 DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));
4726 if (hasLevel(level))
4729 m_data[level].setStorage(dataSize);
4730 m_access[level] = PixelBufferAccess(format, width, height, depth, m_data[level].getPtr());
4733 void TextureLevelArray::clearLevel (int level)
4735 DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));
4737 m_data[level].clear();
4738 m_access[level] = PixelBufferAccess();
4741 void TextureLevelArray::updateSamplerMode (tcu::Sampler::DepthStencilMode mode)
4743 for (int levelNdx = 0; hasLevel(levelNdx); ++levelNdx)
4744 m_effectiveAccess[levelNdx] = tcu::getEffectiveDepthStencilAccess(m_access[levelNdx], mode);
4747 Texture::Texture (deUint32 name, Type type, deBool seamless)
4748 : NamedObject (name)
4750 , m_immutable (false)
4751 , m_sampler (tcu::Sampler::REPEAT_GL,
4752 tcu::Sampler::REPEAT_GL,
4753 tcu::Sampler::REPEAT_GL,
4754 tcu::Sampler::NEAREST_MIPMAP_LINEAR,
4755 tcu::Sampler::LINEAR,
4756 0.0f, // LOD threshold
4757 true, // normalized coords
4758 tcu::Sampler::COMPAREMODE_NONE,
4759 0, // cmp channel ndx
4760 tcu::Vec4(0.0f), // border color
4761 seamless // seamless cube map, Default value is True.
4768 Texture1D::Texture1D (deUint32 name)
4769 : Texture (name, TYPE_1D)
4770 , m_view (0, DE_NULL)
4774 Texture1D::~Texture1D (void)
4778 void Texture1D::allocLevel (int level, const tcu::TextureFormat& format, int width)
4780 m_levels.allocLevel(level, format, width, 1, 1);
4783 bool Texture1D::isComplete (void) const
4785 const int baseLevel = getBaseLevel();
4787 if (hasLevel(baseLevel))
4789 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
4790 const bool mipmap = isMipmapFilter(getSampler().minFilter);
4794 const TextureFormat& format = level0.getFormat();
4795 const int w = level0.getWidth();
4796 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(w));
4798 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4800 if (hasLevel(baseLevel+levelNdx))
4802 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
4803 const int expectedW = getMipLevelSize(w, levelNdx);
4805 if (level.getWidth() != expectedW ||
4806 level.getFormat() != format)
4820 tcu::Vec4 Texture1D::sample (float s, float lod) const
4822 return m_view.sample(getSampler(), s, 0.0f, lod);
4825 void Texture1D::sample4 (tcu::Vec4 output[4], const float packetTexcoords[4], float lodBias) const
4827 const float texWidth = (float)m_view.getWidth();
4829 const float dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4830 const float dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4831 const float dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4832 const float dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4834 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4836 const float& dFdx = (fragNdx > 2) ? dFdx1 : dFdx0;
4837 const float& dFdy = (fragNdx % 2) ? dFdy1 : dFdy0;
4839 const float mu = de::max(de::abs(dFdx), de::abs(dFdy));
4840 const float p = mu * texWidth;
4842 const float lod = deFloatLog2(p) + lodBias;
4844 output[fragNdx] = sample(packetTexcoords[fragNdx], lod);
4848 void Texture1D::updateView (tcu::Sampler::DepthStencilMode mode)
4850 const int baseLevel = getBaseLevel();
4852 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4854 const int width = getLevel(baseLevel).getWidth();
4855 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
4856 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(width)) : 1;
4858 m_levels.updateSamplerMode(mode);
4859 m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
4862 m_view = tcu::Texture2DView(0, DE_NULL);
4865 Texture2D::Texture2D (deUint32 name, bool es2)
4866 : Texture (name, TYPE_2D)
4867 , m_view (0, DE_NULL, es2)
4871 Texture2D::~Texture2D (void)
4875 void Texture2D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height)
4877 m_levels.allocLevel(level, format, width, height, 1);
4880 bool Texture2D::isComplete (void) const
4882 const int baseLevel = getBaseLevel();
4884 if (hasLevel(baseLevel))
4886 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
4887 const bool mipmap = isMipmapFilter(getSampler().minFilter);
4891 const TextureFormat& format = level0.getFormat();
4892 const int w = level0.getWidth();
4893 const int h = level0.getHeight();
4894 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
4896 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4898 if (hasLevel(baseLevel+levelNdx))
4900 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
4901 const int expectedW = getMipLevelSize(w, levelNdx);
4902 const int expectedH = getMipLevelSize(h, levelNdx);
4904 if (level.getWidth() != expectedW ||
4905 level.getHeight() != expectedH ||
4906 level.getFormat() != format)
4920 void Texture2D::updateView (tcu::Sampler::DepthStencilMode mode)
4922 const int baseLevel = getBaseLevel();
4924 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4926 // Update number of levels in mipmap pyramid.
4927 const int width = getLevel(baseLevel).getWidth();
4928 const int height = getLevel(baseLevel).getHeight();
4929 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
4930 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
4932 m_levels.updateSamplerMode(mode);
4933 m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
4936 m_view = tcu::Texture2DView(0, DE_NULL);
4939 tcu::Vec4 Texture2D::sample (float s, float t, float lod) const
4941 return m_view.sample(getSampler(), s, t, lod);
4944 void Texture2D::sample4 (tcu::Vec4 output[4], const tcu::Vec2 packetTexcoords[4], float lodBias) const
4946 const float texWidth = (float)m_view.getWidth();
4947 const float texHeight = (float)m_view.getHeight();
4949 const tcu::Vec2 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4950 const tcu::Vec2 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4951 const tcu::Vec2 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4952 const tcu::Vec2 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4954 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4956 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
4957 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
4959 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
4960 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
4961 const float p = de::max(mu * texWidth, mv * texHeight);
4963 const float lod = deFloatLog2(p) + lodBias;
4965 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), lod);
4969 TextureCube::TextureCube (deUint32 name, deBool seamless)
4970 : Texture(name, TYPE_CUBE_MAP, seamless)
4974 TextureCube::~TextureCube (void)
4978 void TextureCube::clearLevels (void)
4980 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
4981 m_levels[face].clear();
4984 void TextureCube::allocFace (int level, tcu::CubeFace face, const tcu::TextureFormat& format, int width, int height)
4986 m_levels[face].allocLevel(level, format, width, height, 1);
4989 bool TextureCube::isComplete (void) const
4991 const int baseLevel = getBaseLevel();
4993 if (hasFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X))
4995 const int width = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
4996 const int height = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getHeight();
4997 const tcu::TextureFormat& format = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getFormat();
4998 const bool mipmap = isMipmapFilter(getSampler().minFilter);
4999 const int numLevels = mipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5001 if (width != height)
5002 return false; // Non-square is not supported.
5004 // \note Level 0 is always checked for consistency
5005 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
5007 const int levelW = getMipLevelSize(width, levelNdx);
5008 const int levelH = getMipLevelSize(height, levelNdx);
5010 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
5012 if (hasFace(baseLevel+levelNdx, (tcu::CubeFace)face))
5014 const tcu::ConstPixelBufferAccess& level = getFace(baseLevel+levelNdx, (tcu::CubeFace)face);
5016 if (level.getWidth() != levelW ||
5017 level.getHeight() != levelH ||
5018 level.getFormat() != format)
5032 void TextureCube::updateView (tcu::Sampler::DepthStencilMode mode)
5034 const int baseLevel = getBaseLevel();
5035 const tcu::ConstPixelBufferAccess* faces[tcu::CUBEFACE_LAST];
5037 deMemset(&faces[0], 0, sizeof(faces));
5041 const int size = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
5042 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
5043 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(size)) : 1;
5045 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
5047 m_levels[face].updateSamplerMode(mode);
5048 faces[face] = m_levels[face].getEffectiveLevels() + baseLevel;
5051 m_view = tcu::TextureCubeView(numLevels, faces);
5054 m_view = tcu::TextureCubeView(0, faces);
5057 tcu::Vec4 TextureCube::sample (float s, float t, float p, float lod) const
5059 return m_view.sample(getSampler(), s, t, p, lod);
5062 void TextureCube::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5064 const float cubeSide = (float)m_view.getSize();
5066 // Each tex coord might be in a different face.
5068 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5070 const tcu::CubeFace face = tcu::selectCubeFace(packetTexcoords[fragNdx]);
5071 const tcu::Vec2 coords[4] =
5073 tcu::projectToFace(face, packetTexcoords[0]),
5074 tcu::projectToFace(face, packetTexcoords[1]),
5075 tcu::projectToFace(face, packetTexcoords[2]),
5076 tcu::projectToFace(face, packetTexcoords[3]),
5079 const tcu::Vec2 dFdx0 = coords[1] - coords[0];
5080 const tcu::Vec2 dFdx1 = coords[3] - coords[2];
5081 const tcu::Vec2 dFdy0 = coords[2] - coords[0];
5082 const tcu::Vec2 dFdy1 = coords[3] - coords[1];
5084 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5085 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5087 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5088 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5089 const float p = de::max(mu * cubeSide, mv * cubeSide);
5091 const float lod = deFloatLog2(p) + lodBias;
5093 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5097 Texture2DArray::Texture2DArray (deUint32 name)
5098 : Texture (name, TYPE_2D_ARRAY)
5099 , m_view (0, DE_NULL)
5103 Texture2DArray::~Texture2DArray (void)
5107 void Texture2DArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5109 m_levels.allocLevel(level, format, width, height, numLayers);
5112 bool Texture2DArray::isComplete (void) const
5114 const int baseLevel = getBaseLevel();
5116 if (hasLevel(baseLevel))
5118 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
5119 const bool mipmap = isMipmapFilter(getSampler().minFilter);
5123 const TextureFormat& format = level0.getFormat();
5124 const int w = level0.getWidth();
5125 const int h = level0.getHeight();
5126 const int numLayers = level0.getDepth();
5127 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5129 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5131 if (hasLevel(baseLevel+levelNdx))
5133 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
5134 const int expectedW = getMipLevelSize(w, levelNdx);
5135 const int expectedH = getMipLevelSize(h, levelNdx);
5137 if (level.getWidth() != expectedW ||
5138 level.getHeight() != expectedH ||
5139 level.getDepth() != numLayers ||
5140 level.getFormat() != format)
5154 void Texture2DArray::updateView (tcu::Sampler::DepthStencilMode mode)
5156 const int baseLevel = getBaseLevel();
5158 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5160 const int width = getLevel(baseLevel).getWidth();
5161 const int height = getLevel(baseLevel).getHeight();
5162 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
5163 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5165 m_levels.updateSamplerMode(mode);
5166 m_view = tcu::Texture2DArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5169 m_view = tcu::Texture2DArrayView(0, DE_NULL);
5172 tcu::Vec4 Texture2DArray::sample (float s, float t, float r, float lod) const
5174 return m_view.sample(getSampler(), s, t, r, lod);
5177 void Texture2DArray::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5179 const float texWidth = (float)m_view.getWidth();
5180 const float texHeight = (float)m_view.getHeight();
5182 const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5183 const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5184 const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5185 const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5187 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5189 const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5190 const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5192 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5193 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5194 const float p = de::max(mu * texWidth, mv * texHeight);
5196 const float lod = deFloatLog2(p) + lodBias;
5198 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5202 TextureCubeArray::TextureCubeArray (deUint32 name)
5203 : Texture (name, TYPE_CUBE_MAP_ARRAY)
5204 , m_view (0, DE_NULL)
5208 TextureCubeArray::~TextureCubeArray (void)
5212 void TextureCubeArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5214 DE_ASSERT(numLayers % 6 == 0);
5215 m_levels.allocLevel(level, format, width, height, numLayers);
5218 bool TextureCubeArray::isComplete (void) const
5220 const int baseLevel = getBaseLevel();
5222 if (hasLevel(baseLevel))
5224 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
5225 const bool mipmap = isMipmapFilter(getSampler().minFilter);
5229 const TextureFormat& format = level0.getFormat();
5230 const int w = level0.getWidth();
5231 const int h = level0.getHeight();
5232 const int numLayers = level0.getDepth();
5233 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5235 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5237 if (hasLevel(baseLevel+levelNdx))
5239 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
5240 const int expectedW = getMipLevelSize(w, levelNdx);
5241 const int expectedH = getMipLevelSize(h, levelNdx);
5243 if (level.getWidth() != expectedW ||
5244 level.getHeight() != expectedH ||
5245 level.getDepth() != numLayers ||
5246 level.getFormat() != format)
5260 void TextureCubeArray::updateView (tcu::Sampler::DepthStencilMode mode)
5262 const int baseLevel = getBaseLevel();
5264 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5266 const int width = getLevel(baseLevel).getWidth();
5267 const int height = getLevel(baseLevel).getHeight();
5268 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
5269 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5271 m_levels.updateSamplerMode(mode);
5272 m_view = tcu::TextureCubeArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5275 m_view = tcu::TextureCubeArrayView(0, DE_NULL);
5278 tcu::Vec4 TextureCubeArray::sample (float s, float t, float r, float q, float lod) const
5280 return m_view.sample(getSampler(), s, t, r, q, lod);
5283 void TextureCubeArray::sample4 (tcu::Vec4 output[4], const tcu::Vec4 packetTexcoords[4], float lodBias) const
5285 const float cubeSide = (float)m_view.getSize();
5286 const tcu::Vec3 cubeCoords[4] =
5288 packetTexcoords[0].toWidth<3>(),
5289 packetTexcoords[1].toWidth<3>(),
5290 packetTexcoords[2].toWidth<3>(),
5291 packetTexcoords[3].toWidth<3>()
5294 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5296 const tcu::CubeFace face = tcu::selectCubeFace(cubeCoords[fragNdx]);
5297 const tcu::Vec2 faceCoords[4] =
5299 tcu::projectToFace(face, cubeCoords[0]),
5300 tcu::projectToFace(face, cubeCoords[1]),
5301 tcu::projectToFace(face, cubeCoords[2]),
5302 tcu::projectToFace(face, cubeCoords[3]),
5305 const tcu::Vec2 dFdx0 = faceCoords[1] - faceCoords[0];
5306 const tcu::Vec2 dFdx1 = faceCoords[3] - faceCoords[2];
5307 const tcu::Vec2 dFdy0 = faceCoords[2] - faceCoords[0];
5308 const tcu::Vec2 dFdy1 = faceCoords[3] - faceCoords[1];
5310 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5311 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5313 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5314 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5315 const float p = de::max(mu * cubeSide, mv * cubeSide);
5317 const float lod = deFloatLog2(p) + lodBias;
5319 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), packetTexcoords[fragNdx].w(), lod);
5323 Texture3D::Texture3D (deUint32 name)
5324 : Texture (name, TYPE_3D)
5325 , m_view (0, DE_NULL)
5329 Texture3D::~Texture3D (void)
5333 void Texture3D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
5335 m_levels.allocLevel(level, format, width, height, depth);
5338 bool Texture3D::isComplete (void) const
5340 const int baseLevel = getBaseLevel();
5342 if (hasLevel(baseLevel))
5344 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
5345 const bool mipmap = isMipmapFilter(getSampler().minFilter);
5349 const TextureFormat& format = level0.getFormat();
5350 const int w = level0.getWidth();
5351 const int h = level0.getHeight();
5352 const int d = level0.getDepth();
5353 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(w, h, d));
5355 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5357 if (hasLevel(baseLevel+levelNdx))
5359 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
5360 const int expectedW = getMipLevelSize(w, levelNdx);
5361 const int expectedH = getMipLevelSize(h, levelNdx);
5362 const int expectedD = getMipLevelSize(d, levelNdx);
5364 if (level.getWidth() != expectedW ||
5365 level.getHeight() != expectedH ||
5366 level.getDepth() != expectedD ||
5367 level.getFormat() != format)
5381 tcu::Vec4 Texture3D::sample (float s, float t, float r, float lod) const
5383 return m_view.sample(getSampler(), s, t, r, lod);
5386 void Texture3D::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5388 const float texWidth = (float)m_view.getWidth();
5389 const float texHeight = (float)m_view.getHeight();
5390 const float texDepth = (float)m_view.getDepth();
5392 const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5393 const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5394 const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5395 const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5397 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5399 const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5400 const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5402 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5403 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5404 const float mw = de::max(de::abs(dFdx.z()), de::abs(dFdy.z()));
5405 const float p = de::max(de::max(mu * texWidth, mv * texHeight), mw * texDepth);
5407 const float lod = deFloatLog2(p) + lodBias;
5409 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5413 void Texture3D::updateView (tcu::Sampler::DepthStencilMode mode)
5415 const int baseLevel = getBaseLevel();
5417 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5419 const int width = getLevel(baseLevel).getWidth();
5420 const int height = getLevel(baseLevel).getHeight();
5421 const int depth = getLevel(baseLevel).getDepth();
5422 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
5423 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(width, height, depth)) : 1;
5425 m_levels.updateSamplerMode(mode);
5426 m_view = tcu::Texture3DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5429 m_view = tcu::Texture3DView(0, DE_NULL);
5432 Renderbuffer::Renderbuffer (deUint32 name)
5433 : NamedObject (name)
5437 Renderbuffer::~Renderbuffer (void)
5441 void Renderbuffer::setStorage (const TextureFormat& format, int width, int height)
5443 m_data.setStorage(format, width, height);
5446 Framebuffer::Framebuffer (deUint32 name)
5451 Framebuffer::~Framebuffer (void)
5455 VertexArray::VertexArray (deUint32 name, int maxVertexAttribs)
5456 : NamedObject (name)
5457 , m_elementArrayBufferBinding (DE_NULL)
5458 , m_arrays (maxVertexAttribs)
5460 for (int i = 0; i < maxVertexAttribs; ++i)
5462 m_arrays[i].enabled = false;
5463 m_arrays[i].size = 4;
5464 m_arrays[i].stride = 0;
5465 m_arrays[i].type = GL_FLOAT;
5466 m_arrays[i].normalized = false;
5467 m_arrays[i].integer = false;
5468 m_arrays[i].divisor = 0;
5469 m_arrays[i].bufferDeleted = false;
5470 m_arrays[i].bufferBinding = DE_NULL;
5471 m_arrays[i].pointer = DE_NULL;
5475 ShaderProgramObjectContainer::ShaderProgramObjectContainer (deUint32 name, ShaderProgram* program)
5476 : NamedObject (name)
5477 , m_program (program)
5478 , m_deleteFlag (false)
5482 ShaderProgramObjectContainer::~ShaderProgramObjectContainer (void)