1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 *//*!
20 * \file
21 * \brief Reference Rendering Context.
22 *//*--------------------------------------------------------------------*/
23
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 "glwFunctions.hpp"
34 #include "glwEnums.hpp"
35 #include "deMemory.h"
36 #include "rrFragmentOperations.hpp"
37 #include "rrRenderer.hpp"
38
39 namespace sglr
40 {
41
42 using std::vector;
43 using std::map;
44
45 using tcu::Vec2;
46 using tcu::Vec3;
47 using tcu::Vec4;
48 using tcu::IVec2;
49 using tcu::IVec4;
50 using tcu::RGBA;
51
52 // Reference context implementation
53 using namespace rc;
54
55 using tcu::TextureFormat;
56 using tcu::PixelBufferAccess;
57 using tcu::ConstPixelBufferAccess;
58
59 // Utilities for ReferenceContext
60 #define RC_RET_VOID
61
62 #define RC_ERROR_RET(ERR, RET) \
63 do { \
64 setError(ERR); \
65 return RET; \
66 } while (deGetFalse())
67
68 #define RC_IF_ERROR(COND, ERR, RET) \
69 do { \
70 if (COND) \
71 RC_ERROR_RET(ERR, RET); \
72 } while (deGetFalse())
73
nullAccess(void)74 static inline tcu::PixelBufferAccess nullAccess (void)
75 {
76 return tcu::PixelBufferAccess(TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT8), 0, 0, 0, DE_NULL);
77 }
78
isEmpty(const tcu::ConstPixelBufferAccess & access)79 static inline bool isEmpty (const tcu::ConstPixelBufferAccess& access)
80 {
81 return access.getWidth() == 0 || access.getHeight() == 0 || access.getDepth() == 0;
82 }
83
isEmpty(const rr::MultisampleConstPixelBufferAccess & access)84 static inline bool isEmpty (const rr::MultisampleConstPixelBufferAccess& access)
85 {
86 return access.raw().getWidth() == 0 || access.raw().getHeight() == 0 || access.raw().getDepth() == 0;
87 }
88
isEmpty(const IVec4 & rect)89 static inline bool isEmpty (const IVec4& rect)
90 {
91 return rect.z() == 0 || rect.w() == 0;
92 }
93
getNumMipLevels1D(int size)94 inline int getNumMipLevels1D (int size)
95 {
96 return deLog2Floor32(size)+1;
97 }
98
getNumMipLevels2D(int width,int height)99 inline int getNumMipLevels2D (int width, int height)
100 {
101 return deLog2Floor32(de::max(width, height))+1;
102 }
103
getNumMipLevels3D(int width,int height,int depth)104 inline int getNumMipLevels3D (int width, int height, int depth)
105 {
106 return deLog2Floor32(de::max(width, de::max(height, depth)))+1;
107 }
108
getMipLevelSize(int baseLevelSize,int levelNdx)109 inline int getMipLevelSize (int baseLevelSize, int levelNdx)
110 {
111 return de::max(baseLevelSize >> levelNdx, 1);
112 }
113
isMipmapFilter(const tcu::Sampler::FilterMode mode)114 inline bool isMipmapFilter (const tcu::Sampler::FilterMode mode)
115 {
116 return mode != tcu::Sampler::NEAREST && mode != tcu::Sampler::LINEAR;
117 }
118
texTargetToFace(Framebuffer::TexTarget target)119 static tcu::CubeFace texTargetToFace (Framebuffer::TexTarget target)
120 {
121 switch (target)
122 {
123 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X: return tcu::CUBEFACE_NEGATIVE_X;
124 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X: return tcu::CUBEFACE_POSITIVE_X;
125 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y: return tcu::CUBEFACE_NEGATIVE_Y;
126 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y: return tcu::CUBEFACE_POSITIVE_Y;
127 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z: return tcu::CUBEFACE_NEGATIVE_Z;
128 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z: return tcu::CUBEFACE_POSITIVE_Z;
129 default: return tcu::CUBEFACE_LAST;
130 }
131 }
132
texLayeredTypeToTarget(Texture::Type type)133 static Framebuffer::TexTarget texLayeredTypeToTarget (Texture::Type type)
134 {
135 switch (type)
136 {
137 case Texture::TYPE_2D_ARRAY: return Framebuffer::TEXTARGET_2D_ARRAY;
138 case Texture::TYPE_3D: return Framebuffer::TEXTARGET_3D;
139 case Texture::TYPE_CUBE_MAP_ARRAY: return Framebuffer::TEXTARGET_CUBE_MAP_ARRAY;
140 default: return Framebuffer::TEXTARGET_LAST;
141 }
142 }
143
mapGLCubeFace(deUint32 face)144 static tcu::CubeFace mapGLCubeFace (deUint32 face)
145 {
146 switch (face)
147 {
148 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return tcu::CUBEFACE_NEGATIVE_X;
149 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return tcu::CUBEFACE_POSITIVE_X;
150 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return tcu::CUBEFACE_NEGATIVE_Y;
151 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return tcu::CUBEFACE_POSITIVE_Y;
152 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return tcu::CUBEFACE_NEGATIVE_Z;
153 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return tcu::CUBEFACE_POSITIVE_Z;
154 default: return tcu::CUBEFACE_LAST;
155 }
156 }
157
toTextureFormat(const tcu::PixelFormat & pixelFmt)158 tcu::TextureFormat toTextureFormat (const tcu::PixelFormat& pixelFmt)
159 {
160 static const struct
161 {
162 tcu::PixelFormat pixelFmt;
163 tcu::TextureFormat texFmt;
164 } pixelFormatMap[] =
165 {
166 { tcu::PixelFormat(8,8,8,8), tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) },
167 { tcu::PixelFormat(8,8,8,0), tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8) },
168 { tcu::PixelFormat(4,4,4,4), tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_SHORT_4444) },
169 { tcu::PixelFormat(5,5,5,1), tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_SHORT_5551) },
170 { tcu::PixelFormat(5,6,5,0), tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_SHORT_565) }
171 };
172
173 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pixelFormatMap); ndx++)
174 {
175 if (pixelFormatMap[ndx].pixelFmt == pixelFmt)
176 return pixelFormatMap[ndx].texFmt;
177 }
178
179 TCU_FAIL("Can't map pixel format to texture format");
180 }
181
toNonSRGBFormat(const tcu::TextureFormat & fmt)182 tcu::TextureFormat toNonSRGBFormat (const tcu::TextureFormat& fmt)
183 {
184 switch (fmt.order)
185 {
186 case tcu::TextureFormat::sRGB:
187 return tcu::TextureFormat(tcu::TextureFormat::RGB, fmt.type);
188 case tcu::TextureFormat::sRGBA:
189 return tcu::TextureFormat(tcu::TextureFormat::RGBA, fmt.type);
190 default:
191 return fmt;
192 }
193 }
194
getDepthFormat(int depthBits)195 tcu::TextureFormat getDepthFormat (int depthBits)
196 {
197 switch (depthBits)
198 {
199 case 8: return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
200 case 16: return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
201 case 24: return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8);
202 case 32: return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
203 default:
204 TCU_FAIL("Can't map depth buffer format");
205 }
206 }
207
getStencilFormat(int stencilBits)208 tcu::TextureFormat getStencilFormat (int stencilBits)
209 {
210 switch (stencilBits)
211 {
212 case 8: return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
213 case 16: return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT16);
214 case 24: return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT_24_8);
215 case 32: return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32);
216 default:
217 TCU_FAIL("Can't map depth buffer format");
218 }
219 }
220
intersect(const tcu::IVec4 & a,const tcu::IVec4 & b)221 static inline tcu::IVec4 intersect (const tcu::IVec4& a, const tcu::IVec4& b)
222 {
223 int x0 = de::max(a.x(), b.x());
224 int y0 = de::max(a.y(), b.y());
225 int x1 = de::min(a.x()+a.z(), b.x()+b.z());
226 int y1 = de::min(a.y()+a.w(), b.y()+b.w());
227 int w = de::max(0, x1-x0);
228 int h = de::max(0, y1-y0);
229
230 return tcu::IVec4(x0, y0, w, h);
231 }
232
getBufferRect(const rr::MultisampleConstPixelBufferAccess & access)233 static inline tcu::IVec4 getBufferRect (const rr::MultisampleConstPixelBufferAccess& access)
234 {
235 return tcu::IVec4(0, 0, access.raw().getHeight(), access.raw().getDepth());
236 }
237
ReferenceContextLimits(const glu::RenderContext & renderCtx)238 ReferenceContextLimits::ReferenceContextLimits (const glu::RenderContext& renderCtx)
239 : contextType (renderCtx.getType())
240 , maxTextureImageUnits (0)
241 , maxTexture2DSize (0)
242 , maxTextureCubeSize (0)
243 , maxTexture2DArrayLayers (0)
244 , maxTexture3DSize (0)
245 , maxRenderbufferSize (0)
246 , maxVertexAttribs (0)
247 {
248 const glw::Functions& gl = renderCtx.getFunctions();
249
250 gl.getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);
251 gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexture2DSize);
252 gl.getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxTextureCubeSize);
253 gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxRenderbufferSize);
254 gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
255
256 if (contextSupports(contextType, glu::ApiType::es(3,0)) || glu::isContextTypeGLCore(contextType))
257 {
258 gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTexture2DArrayLayers);
259 gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxTexture3DSize);
260 }
261
262 // Limit texture sizes to supported values
263 maxTexture2DSize = de::min(maxTexture2DSize, (int)MAX_TEXTURE_SIZE);
264 maxTextureCubeSize = de::min(maxTextureCubeSize, (int)MAX_TEXTURE_SIZE);
265 maxTexture3DSize = de::min(maxTexture3DSize, (int)MAX_TEXTURE_SIZE);
266
267 GLU_EXPECT_NO_ERROR(gl.getError(), GL_NO_ERROR);
268
269 // \todo [pyry] Figure out following things:
270 // + supported fbo configurations
271 // ...
272
273 // \todo [2013-08-01 pyry] Do we want to make these conditional based on renderCtx?
274 addExtension("GL_EXT_color_buffer_half_float");
275 addExtension("GL_EXT_color_buffer_float");
276
277 if (contextSupports(contextType, glu::ApiType::es(3,1)))
278 addExtension("GL_EXT_texture_cube_map_array");
279 }
280
addExtension(const char * extension)281 void ReferenceContextLimits::addExtension (const char* extension)
282 {
283 extensionList.push_back(extension);
284
285 if (!extensionStr.empty())
286 extensionStr += " ";
287 extensionStr += extension;
288 }
289
ReferenceContextBuffers(const tcu::PixelFormat & colorBits,int depthBits,int stencilBits,int width,int height,int samples)290 ReferenceContextBuffers::ReferenceContextBuffers (const tcu::PixelFormat& colorBits, int depthBits, int stencilBits, int width, int height, int samples)
291 {
292 m_colorbuffer.setStorage(toTextureFormat(colorBits), samples, width, height);
293
294 if (depthBits > 0)
295 m_depthbuffer.setStorage(getDepthFormat(depthBits), samples, width, height);
296
297 if (stencilBits > 0)
298 m_stencilbuffer.setStorage(getStencilFormat(stencilBits), samples, width, height);
299 }
300
StencilState(void)301 ReferenceContext::StencilState::StencilState (void)
302 : func (GL_ALWAYS)
303 , ref (0)
304 , opMask (~0u)
305 , opStencilFail (GL_KEEP)
306 , opDepthFail (GL_KEEP)
307 , opDepthPass (GL_KEEP)
308 , writeMask (~0u)
309 {
310 }
311
ReferenceContext(const ReferenceContextLimits & limits,const rr::MultisamplePixelBufferAccess & colorbuffer,const rr::MultisamplePixelBufferAccess & depthbuffer,const rr::MultisamplePixelBufferAccess & stencilbuffer)312 ReferenceContext::ReferenceContext (const ReferenceContextLimits& limits, const rr::MultisamplePixelBufferAccess& colorbuffer, const rr::MultisamplePixelBufferAccess& depthbuffer, const rr::MultisamplePixelBufferAccess& stencilbuffer)
313 : Context (limits.contextType)
314 , m_limits (limits)
315 , m_defaultColorbuffer (colorbuffer)
316 , m_defaultDepthbuffer (depthbuffer)
317 , m_defaultStencilbuffer (stencilbuffer)
318 , m_clientVertexArray (0, m_limits.maxVertexAttribs)
319
320 , m_viewport (0, 0, colorbuffer.raw().getHeight(), colorbuffer.raw().getDepth())
321
322 , m_activeTexture (0)
323 , m_textureUnits (m_limits.maxTextureImageUnits)
324 , m_emptyTex1D ()
325 , m_emptyTex2D ()
326 , m_emptyTexCube ()
327 , m_emptyTex2DArray ()
328 , m_emptyTex3D ()
329 , m_emptyTexCubeArray ()
330
331 , m_pixelUnpackRowLength (0)
332 , m_pixelUnpackSkipRows (0)
333 , m_pixelUnpackSkipPixels (0)
334 , m_pixelUnpackImageHeight (0)
335 , m_pixelUnpackSkipImages (0)
336 , m_pixelUnpackAlignment (4)
337 , m_pixelPackAlignment (4)
338
339 , m_readFramebufferBinding (DE_NULL)
340 , m_drawFramebufferBinding (DE_NULL)
341 , m_renderbufferBinding (DE_NULL)
342 , m_vertexArrayBinding (DE_NULL)
343 , m_currentProgram (DE_NULL)
344
345 , m_arrayBufferBinding (DE_NULL)
346 , m_pixelPackBufferBinding (DE_NULL)
347 , m_pixelUnpackBufferBinding (DE_NULL)
348 , m_transformFeedbackBufferBinding (DE_NULL)
349 , m_uniformBufferBinding (DE_NULL)
350 , m_copyReadBufferBinding (DE_NULL)
351 , m_copyWriteBufferBinding (DE_NULL)
352 , m_drawIndirectBufferBinding (DE_NULL)
353
354 , m_clearColor (0.0f, 0.0f, 0.0f, 0.0f)
355 , m_clearDepth (1.0f)
356 , m_clearStencil (0)
357 , m_scissorEnabled (false)
358 , m_scissorBox (m_viewport)
359 , m_stencilTestEnabled (false)
360 , m_depthTestEnabled (false)
361 , m_depthFunc (GL_LESS)
362 , m_depthRangeNear (0.0f)
363 , m_depthRangeFar (1.0f)
364 , m_polygonOffsetFactor (0.0f)
365 , m_polygonOffsetUnits (0.0f)
366 , m_polygonOffsetFillEnabled (false)
367 , m_provokingFirstVertexConvention (false)
368 , m_blendEnabled (false)
369 , m_blendModeRGB (GL_FUNC_ADD)
370 , m_blendModeAlpha (GL_FUNC_ADD)
371 , m_blendFactorSrcRGB (GL_ONE)
372 , m_blendFactorDstRGB (GL_ZERO)
373 , m_blendFactorSrcAlpha (GL_ONE)
374 , m_blendFactorDstAlpha (GL_ZERO)
375 , m_blendColor (0.0f, 0.0f, 0.0f, 0.0f)
376 , m_sRGBUpdateEnabled (true)
377 , m_depthClampEnabled (false)
378 , m_colorMask (true, true, true, true)
379 , m_depthMask (true)
380 , m_currentAttribs (m_limits.maxVertexAttribs, rr::GenericVec4(tcu::Vec4(0, 0, 0, 1)))
381 , m_lineWidth (1.0f)
382 , m_primitiveRestartFixedIndex (false)
383 , m_primitiveRestartSettableIndex (false)
384 , m_primitiveRestartIndex (0)
385
386 , m_lastError (GL_NO_ERROR)
387 {
388 // Create empty textures to be used when texture objects are incomplete.
389 m_emptyTex1D.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
390 m_emptyTex1D.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
391 m_emptyTex1D.getSampler().minFilter = tcu::Sampler::NEAREST;
392 m_emptyTex1D.getSampler().magFilter = tcu::Sampler::NEAREST;
393 m_emptyTex1D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1);
394 m_emptyTex1D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
395 m_emptyTex1D.updateView();
396
397 m_emptyTex2D.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
398 m_emptyTex2D.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
399 m_emptyTex2D.getSampler().minFilter = tcu::Sampler::NEAREST;
400 m_emptyTex2D.getSampler().magFilter = tcu::Sampler::NEAREST;
401 m_emptyTex2D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
402 m_emptyTex2D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
403 m_emptyTex2D.updateView();
404
405 m_emptyTexCube.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
406 m_emptyTexCube.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
407 m_emptyTexCube.getSampler().minFilter = tcu::Sampler::NEAREST;
408 m_emptyTexCube.getSampler().magFilter = tcu::Sampler::NEAREST;
409 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
410 {
411 m_emptyTexCube.allocFace(0, (tcu::CubeFace)face, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
412 m_emptyTexCube.getFace(0, (tcu::CubeFace)face).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
413 }
414 m_emptyTexCube.updateView();
415
416 m_emptyTex2DArray.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
417 m_emptyTex2DArray.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
418 m_emptyTex2DArray.getSampler().minFilter = tcu::Sampler::NEAREST;
419 m_emptyTex2DArray.getSampler().magFilter = tcu::Sampler::NEAREST;
420 m_emptyTex2DArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
421 m_emptyTex2DArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
422 m_emptyTex2DArray.updateView();
423
424 m_emptyTex3D.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
425 m_emptyTex3D.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
426 m_emptyTex3D.getSampler().wrapR = tcu::Sampler::CLAMP_TO_EDGE;
427 m_emptyTex3D.getSampler().minFilter = tcu::Sampler::NEAREST;
428 m_emptyTex3D.getSampler().magFilter = tcu::Sampler::NEAREST;
429 m_emptyTex3D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
430 m_emptyTex3D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
431 m_emptyTex3D.updateView();
432
433 m_emptyTexCubeArray.getSampler().wrapS = tcu::Sampler::CLAMP_TO_EDGE;
434 m_emptyTexCubeArray.getSampler().wrapT = tcu::Sampler::CLAMP_TO_EDGE;
435 m_emptyTexCubeArray.getSampler().minFilter = tcu::Sampler::NEAREST;
436 m_emptyTexCubeArray.getSampler().magFilter = tcu::Sampler::NEAREST;
437 m_emptyTexCubeArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 6);
438 for (int faceNdx = 0; faceNdx < 6; faceNdx++)
439 m_emptyTexCubeArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, faceNdx);
440 m_emptyTexCubeArray.updateView();
441
442 if (glu::isContextTypeGLCore(getType()))
443 m_sRGBUpdateEnabled = false;
444 }
445
~ReferenceContext(void)446 ReferenceContext::~ReferenceContext (void)
447 {
448 // Destroy all objects -- verifies that ref counting works
449 {
450 vector<VertexArray*> vertexArrays;
451 m_vertexArrays.getAll(vertexArrays);
452 for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
453 deleteVertexArray(*i);
454
455 DE_ASSERT(m_clientVertexArray.getRefCount() == 1);
456 }
457
458 {
459 vector<Texture*> textures;
460 m_textures.getAll(textures);
461 for (vector<Texture*>::iterator i = textures.begin(); i != textures.end(); i++)
462 deleteTexture(*i);
463 }
464
465 {
466 vector<Framebuffer*> framebuffers;
467 m_framebuffers.getAll(framebuffers);
468 for (vector<Framebuffer*>::iterator i = framebuffers.begin(); i != framebuffers.end(); i++)
469 deleteFramebuffer(*i);
470 }
471
472 {
473 vector<Renderbuffer*> renderbuffers;
474 m_renderbuffers.getAll(renderbuffers);
475 for (vector<Renderbuffer*>::iterator i = renderbuffers.begin(); i != renderbuffers.end(); i++)
476 deleteRenderbuffer(*i);
477 }
478
479 {
480 vector<DataBuffer*> buffers;
481 m_buffers.getAll(buffers);
482 for (vector<DataBuffer*>::iterator i = buffers.begin(); i != buffers.end(); i++)
483 deleteBuffer(*i);
484 }
485
486 {
487 vector<ShaderProgramObjectContainer*> programs;
488 m_programs.getAll(programs);
489 for (vector<ShaderProgramObjectContainer*>::iterator i = programs.begin(); i != programs.end(); i++)
490 deleteProgramObject(*i);
491 }
492 }
493
activeTexture(deUint32 texture)494 void ReferenceContext::activeTexture (deUint32 texture)
495 {
496 if (deInBounds32(texture, GL_TEXTURE0, GL_TEXTURE0 + (deUint32)m_textureUnits.size()))
497 m_activeTexture = texture - GL_TEXTURE0;
498 else
499 setError(GL_INVALID_ENUM);
500 }
501
setTex1DBinding(int unitNdx,Texture1D * texture)502 void ReferenceContext::setTex1DBinding (int unitNdx, Texture1D* texture)
503 {
504 if (m_textureUnits[unitNdx].tex1DBinding)
505 {
506 m_textures.releaseReference(m_textureUnits[unitNdx].tex1DBinding);
507 m_textureUnits[unitNdx].tex1DBinding = DE_NULL;
508 }
509
510 if (texture)
511 {
512 m_textures.acquireReference(texture);
513 m_textureUnits[unitNdx].tex1DBinding = texture;
514 }
515 }
516
setTex2DBinding(int unitNdx,Texture2D * texture)517 void ReferenceContext::setTex2DBinding (int unitNdx, Texture2D* texture)
518 {
519 if (m_textureUnits[unitNdx].tex2DBinding)
520 {
521 m_textures.releaseReference(m_textureUnits[unitNdx].tex2DBinding);
522 m_textureUnits[unitNdx].tex2DBinding = DE_NULL;
523 }
524
525 if (texture)
526 {
527 m_textures.acquireReference(texture);
528 m_textureUnits[unitNdx].tex2DBinding = texture;
529 }
530 }
531
setTexCubeBinding(int unitNdx,TextureCube * texture)532 void ReferenceContext::setTexCubeBinding (int unitNdx, TextureCube* texture)
533 {
534 if (m_textureUnits[unitNdx].texCubeBinding)
535 {
536 m_textures.releaseReference(m_textureUnits[unitNdx].texCubeBinding);
537 m_textureUnits[unitNdx].texCubeBinding = DE_NULL;
538 }
539
540 if (texture)
541 {
542 m_textures.acquireReference(texture);
543 m_textureUnits[unitNdx].texCubeBinding = texture;
544 }
545 }
546
setTex2DArrayBinding(int unitNdx,Texture2DArray * texture)547 void ReferenceContext::setTex2DArrayBinding (int unitNdx, Texture2DArray* texture)
548 {
549 if (m_textureUnits[unitNdx].tex2DArrayBinding)
550 {
551 m_textures.releaseReference(m_textureUnits[unitNdx].tex2DArrayBinding);
552 m_textureUnits[unitNdx].tex2DArrayBinding = DE_NULL;
553 }
554
555 if (texture)
556 {
557 m_textures.acquireReference(texture);
558 m_textureUnits[unitNdx].tex2DArrayBinding = texture;
559 }
560 }
561
setTex3DBinding(int unitNdx,Texture3D * texture)562 void ReferenceContext::setTex3DBinding (int unitNdx, Texture3D* texture)
563 {
564 if (m_textureUnits[unitNdx].tex3DBinding)
565 {
566 m_textures.releaseReference(m_textureUnits[unitNdx].tex3DBinding);
567 m_textureUnits[unitNdx].tex3DBinding = DE_NULL;
568 }
569
570 if (texture)
571 {
572 m_textures.acquireReference(texture);
573 m_textureUnits[unitNdx].tex3DBinding = texture;
574 }
575 }
576
setTexCubeArrayBinding(int unitNdx,TextureCubeArray * texture)577 void ReferenceContext::setTexCubeArrayBinding (int unitNdx, TextureCubeArray* texture)
578 {
579 if (m_textureUnits[unitNdx].texCubeArrayBinding)
580 {
581 m_textures.releaseReference(m_textureUnits[unitNdx].texCubeArrayBinding);
582 m_textureUnits[unitNdx].texCubeArrayBinding = DE_NULL;
583 }
584
585 if (texture)
586 {
587 m_textures.acquireReference(texture);
588 m_textureUnits[unitNdx].texCubeArrayBinding = texture;
589 }
590 }
591
bindTexture(deUint32 target,deUint32 texture)592 void ReferenceContext::bindTexture (deUint32 target, deUint32 texture)
593 {
594 int unitNdx = m_activeTexture;
595
596 RC_IF_ERROR(target != GL_TEXTURE_1D &&
597 target != GL_TEXTURE_2D &&
598 target != GL_TEXTURE_CUBE_MAP &&
599 target != GL_TEXTURE_2D_ARRAY &&
600 target != GL_TEXTURE_3D &&
601 target != GL_TEXTURE_CUBE_MAP_ARRAY,
602 GL_INVALID_ENUM, RC_RET_VOID);
603
604 RC_IF_ERROR(glu::isContextTypeES(m_limits.contextType) && (target == GL_TEXTURE_1D), GL_INVALID_ENUM, RC_RET_VOID);
605
606 if (texture == 0)
607 {
608 // Clear binding.
609 switch (target)
610 {
611 case GL_TEXTURE_1D: setTex1DBinding (unitNdx, DE_NULL); break;
612 case GL_TEXTURE_2D: setTex2DBinding (unitNdx, DE_NULL); break;
613 case GL_TEXTURE_CUBE_MAP: setTexCubeBinding (unitNdx, DE_NULL); break;
614 case GL_TEXTURE_2D_ARRAY: setTex2DArrayBinding (unitNdx, DE_NULL); break;
615 case GL_TEXTURE_3D: setTex3DBinding (unitNdx, DE_NULL); break;
616 case GL_TEXTURE_CUBE_MAP_ARRAY: setTexCubeArrayBinding (unitNdx, DE_NULL); break;
617 default:
618 DE_ASSERT(false);
619 }
620 }
621 else
622 {
623 Texture* texObj = m_textures.find(texture);
624
625 if (texObj)
626 {
627 // Validate type.
628 Texture::Type expectedType = Texture::TYPE_LAST;
629 switch (target)
630 {
631 case GL_TEXTURE_1D: expectedType = Texture::TYPE_1D; break;
632 case GL_TEXTURE_2D: expectedType = Texture::TYPE_2D; break;
633 case GL_TEXTURE_CUBE_MAP: expectedType = Texture::TYPE_CUBE_MAP; break;
634 case GL_TEXTURE_2D_ARRAY: expectedType = Texture::TYPE_2D_ARRAY; break;
635 case GL_TEXTURE_3D: expectedType = Texture::TYPE_3D; break;
636 case GL_TEXTURE_CUBE_MAP_ARRAY: expectedType = Texture::TYPE_CUBE_MAP_ARRAY; break;
637 default:
638 DE_ASSERT(false);
639 }
640 RC_IF_ERROR(texObj->getType() != expectedType, GL_INVALID_OPERATION, RC_RET_VOID);
641 }
642 else
643 {
644 // New texture object.
645 switch (target)
646 {
647 case GL_TEXTURE_1D: texObj = new Texture1D (texture); break;
648 case GL_TEXTURE_2D: texObj = new Texture2D (texture); break;
649 case GL_TEXTURE_CUBE_MAP: texObj = new TextureCube (texture); break;
650 case GL_TEXTURE_2D_ARRAY: texObj = new Texture2DArray (texture); break;
651 case GL_TEXTURE_3D: texObj = new Texture3D (texture); break;
652 case GL_TEXTURE_CUBE_MAP_ARRAY: texObj = new TextureCubeArray (texture); break;
653 default:
654 DE_ASSERT(false);
655 }
656
657 m_textures.insert(texObj);
658 }
659
660 switch (target)
661 {
662 case GL_TEXTURE_1D: setTex1DBinding (unitNdx, static_cast<Texture1D*> (texObj)); break;
663 case GL_TEXTURE_2D: setTex2DBinding (unitNdx, static_cast<Texture2D*> (texObj)); break;
664 case GL_TEXTURE_CUBE_MAP: setTexCubeBinding (unitNdx, static_cast<TextureCube*> (texObj)); break;
665 case GL_TEXTURE_2D_ARRAY: setTex2DArrayBinding (unitNdx, static_cast<Texture2DArray*> (texObj)); break;
666 case GL_TEXTURE_3D: setTex3DBinding (unitNdx, static_cast<Texture3D*> (texObj)); break;
667 case GL_TEXTURE_CUBE_MAP_ARRAY: setTexCubeArrayBinding (unitNdx, static_cast<TextureCubeArray*> (texObj)); break;
668 default:
669 DE_ASSERT(false);
670 }
671 }
672 }
673
genTextures(int numTextures,deUint32 * textures)674 void ReferenceContext::genTextures (int numTextures, deUint32* textures)
675 {
676 while (numTextures--)
677 *textures++ = m_textures.allocateName();
678 }
679
deleteTextures(int numTextures,const deUint32 * textures)680 void ReferenceContext::deleteTextures (int numTextures, const deUint32* textures)
681 {
682 for (int i = 0; i < numTextures; i++)
683 {
684 deUint32 name = textures[i];
685 Texture* texture = name ? m_textures.find(name) : DE_NULL;
686
687 if (texture)
688 deleteTexture(texture);
689 }
690 }
691
deleteTexture(Texture * texture)692 void ReferenceContext::deleteTexture (Texture* texture)
693 {
694 // Unbind from context
695 for (int unitNdx = 0; unitNdx < (int)m_textureUnits.size(); unitNdx++)
696 {
697 if (m_textureUnits[unitNdx].tex1DBinding == texture) setTex1DBinding (unitNdx, DE_NULL);
698 else if (m_textureUnits[unitNdx].tex2DBinding == texture) setTex2DBinding (unitNdx, DE_NULL);
699 else if (m_textureUnits[unitNdx].texCubeBinding == texture) setTexCubeBinding (unitNdx, DE_NULL);
700 else if (m_textureUnits[unitNdx].tex2DArrayBinding == texture) setTex2DArrayBinding (unitNdx, DE_NULL);
701 else if (m_textureUnits[unitNdx].tex3DBinding == texture) setTex3DBinding (unitNdx, DE_NULL);
702 else if (m_textureUnits[unitNdx].texCubeArrayBinding == texture) setTexCubeArrayBinding (unitNdx, DE_NULL);
703 }
704
705 // Unbind from currently bound framebuffers
706 for (int ndx = 0; ndx < 2; ndx++)
707 {
708 rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
709 if (framebufferBinding)
710 {
711 int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
712 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
713
714 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
715 {
716 Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
717 if (attachment.name == texture->getName())
718 {
719 for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
720 releaseFboAttachmentReference(attachment);
721 attachment = Framebuffer::Attachment();
722 }
723 }
724 }
725 }
726
727 DE_ASSERT(texture->getRefCount() == 1);
728 m_textures.releaseReference(texture);
729 }
730
bindFramebuffer(deUint32 target,deUint32 name)731 void ReferenceContext::bindFramebuffer (deUint32 target, deUint32 name)
732 {
733 Framebuffer* fbo = DE_NULL;
734
735 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
736 target != GL_DRAW_FRAMEBUFFER &&
737 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
738
739 if (name != 0)
740 {
741 // Find or create framebuffer object.
742 fbo = m_framebuffers.find(name);
743 if (!fbo)
744 {
745 fbo = new Framebuffer(name);
746 m_framebuffers.insert(fbo);
747 }
748 }
749
750 for (int ndx = 0; ndx < 2; ndx++)
751 {
752 deUint32 bindingTarget = ndx ? GL_DRAW_FRAMEBUFFER : GL_READ_FRAMEBUFFER;
753 rc::Framebuffer*& binding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
754
755 if (target != GL_FRAMEBUFFER && target != bindingTarget)
756 continue; // Doesn't match this target.
757
758 // Remove old references
759 if (binding)
760 {
761 // Clear all attachment point references
762 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
763 releaseFboAttachmentReference(binding->getAttachment((Framebuffer::AttachmentPoint)point));
764
765 m_framebuffers.releaseReference(binding);
766 }
767
768 // Create new references
769 if (fbo)
770 {
771 m_framebuffers.acquireReference(fbo);
772
773 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
774 acquireFboAttachmentReference(fbo->getAttachment((Framebuffer::AttachmentPoint)point));
775 }
776
777 binding = fbo;
778 }
779 }
780
genFramebuffers(int numFramebuffers,deUint32 * framebuffers)781 void ReferenceContext::genFramebuffers (int numFramebuffers, deUint32* framebuffers)
782 {
783 while (numFramebuffers--)
784 *framebuffers++ = m_framebuffers.allocateName();
785 }
786
deleteFramebuffer(Framebuffer * framebuffer)787 void ReferenceContext::deleteFramebuffer (Framebuffer* framebuffer)
788 {
789 // Remove bindings.
790 if (m_drawFramebufferBinding == framebuffer) bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
791 if (m_readFramebufferBinding == framebuffer) bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
792
793 DE_ASSERT(framebuffer->getRefCount() == 1);
794 m_framebuffers.releaseReference(framebuffer);
795 }
796
deleteFramebuffers(int numFramebuffers,const deUint32 * framebuffers)797 void ReferenceContext::deleteFramebuffers (int numFramebuffers, const deUint32* framebuffers)
798 {
799 for (int i = 0; i < numFramebuffers; i++)
800 {
801 deUint32 name = framebuffers[i];
802 Framebuffer* framebuffer = name ? m_framebuffers.find(name) : DE_NULL;
803
804 if (framebuffer)
805 deleteFramebuffer(framebuffer);
806 }
807 }
808
bindRenderbuffer(deUint32 target,deUint32 name)809 void ReferenceContext::bindRenderbuffer (deUint32 target, deUint32 name)
810 {
811 Renderbuffer* rbo = DE_NULL;
812
813 RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
814
815 if (name != 0)
816 {
817 rbo = m_renderbuffers.find(name);
818 if (!rbo)
819 {
820 rbo = new Renderbuffer(name);
821 m_renderbuffers.insert(rbo);
822 }
823 }
824
825 // Remove old reference
826 if (m_renderbufferBinding)
827 m_renderbuffers.releaseReference(m_renderbufferBinding);
828
829 // Create new reference
830 if (rbo)
831 m_renderbuffers.acquireReference(rbo);
832
833 m_renderbufferBinding = rbo;
834 }
835
genRenderbuffers(int numRenderbuffers,deUint32 * renderbuffers)836 void ReferenceContext::genRenderbuffers (int numRenderbuffers, deUint32* renderbuffers)
837 {
838 while (numRenderbuffers--)
839 *renderbuffers++ = m_renderbuffers.allocateName();
840 }
841
deleteRenderbuffer(Renderbuffer * renderbuffer)842 void ReferenceContext::deleteRenderbuffer (Renderbuffer* renderbuffer)
843 {
844 if (m_renderbufferBinding == renderbuffer)
845 bindRenderbuffer(GL_RENDERBUFFER, 0);
846
847 // Unbind from currently bound framebuffers
848 for (int ndx = 0; ndx < 2; ndx++)
849 {
850 rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
851 if (framebufferBinding)
852 {
853 int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
854 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
855
856 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
857 {
858 Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
859 if (attachment.name == renderbuffer->getName())
860 {
861 for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
862 releaseFboAttachmentReference(attachment);
863 attachment = Framebuffer::Attachment();
864 }
865 }
866 }
867 }
868
869 DE_ASSERT(renderbuffer->getRefCount() == 1);
870 m_renderbuffers.releaseReference(renderbuffer);
871 }
872
deleteRenderbuffers(int numRenderbuffers,const deUint32 * renderbuffers)873 void ReferenceContext::deleteRenderbuffers (int numRenderbuffers, const deUint32* renderbuffers)
874 {
875 for (int i = 0; i < numRenderbuffers; i++)
876 {
877 deUint32 name = renderbuffers[i];
878 Renderbuffer* renderbuffer = name ? m_renderbuffers.find(name) : DE_NULL;
879
880 if (renderbuffer)
881 deleteRenderbuffer(renderbuffer);
882 }
883 }
884
pixelStorei(deUint32 pname,int param)885 void ReferenceContext::pixelStorei (deUint32 pname, int param)
886 {
887 switch (pname)
888 {
889 case GL_UNPACK_ALIGNMENT:
890 RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
891 m_pixelUnpackAlignment = param;
892 break;
893
894 case GL_PACK_ALIGNMENT:
895 RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
896 m_pixelPackAlignment = param;
897 break;
898
899 case GL_UNPACK_ROW_LENGTH:
900 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
901 m_pixelUnpackRowLength = param;
902 break;
903
904 case GL_UNPACK_SKIP_ROWS:
905 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
906 m_pixelUnpackSkipRows = param;
907 break;
908
909 case GL_UNPACK_SKIP_PIXELS:
910 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
911 m_pixelUnpackSkipPixels = param;
912 break;
913
914 case GL_UNPACK_IMAGE_HEIGHT:
915 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
916 m_pixelUnpackImageHeight = param;
917 break;
918
919 case GL_UNPACK_SKIP_IMAGES:
920 RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
921 m_pixelUnpackSkipImages = param;
922 break;
923
924 default:
925 setError(GL_INVALID_ENUM);
926 }
927 }
928
getUnpack2DAccess(const tcu::TextureFormat & format,int width,int height,const void * data)929 tcu::ConstPixelBufferAccess ReferenceContext::getUnpack2DAccess (const tcu::TextureFormat& format, int width, int height, const void* data)
930 {
931 int pixelSize = format.getPixelSize();
932 int rowLen = m_pixelUnpackRowLength > 0 ? m_pixelUnpackRowLength : width;
933 int rowPitch = deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
934 const deUint8* ptr = (const deUint8*)data + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;
935
936 return tcu::ConstPixelBufferAccess(format, width, height, 1, rowPitch, 0, ptr);
937 }
938
getUnpack3DAccess(const tcu::TextureFormat & format,int width,int height,int depth,const void * data)939 tcu::ConstPixelBufferAccess ReferenceContext::getUnpack3DAccess (const tcu::TextureFormat& format, int width, int height, int depth, const void* data)
940 {
941 int pixelSize = format.getPixelSize();
942 int rowLen = m_pixelUnpackRowLength > 0 ? m_pixelUnpackRowLength : width;
943 int imageHeight = m_pixelUnpackImageHeight > 0 ? m_pixelUnpackImageHeight : height;
944 int rowPitch = deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
945 int slicePitch = imageHeight*rowPitch;
946 const deUint8* ptr = (const deUint8*)data + m_pixelUnpackSkipImages*slicePitch + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;
947
948 return tcu::ConstPixelBufferAccess(format, width, height, depth, rowPitch, slicePitch, ptr);
949 }
950
mapInternalFormat(deUint32 internalFormat)951 static tcu::TextureFormat mapInternalFormat (deUint32 internalFormat)
952 {
953 switch (internalFormat)
954 {
955 case GL_ALPHA: return TextureFormat(TextureFormat::A, TextureFormat::UNORM_INT8);
956 case GL_LUMINANCE: return TextureFormat(TextureFormat::L, TextureFormat::UNORM_INT8);
957 case GL_LUMINANCE_ALPHA: return TextureFormat(TextureFormat::LA, TextureFormat::UNORM_INT8);
958 case GL_RGB: return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8);
959 case GL_RGBA: return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
960
961 default:
962 return glu::mapGLInternalFormat(internalFormat);
963 }
964 }
965
depthValueFloatClampCopy(const PixelBufferAccess & dst,const ConstPixelBufferAccess & src)966 static void depthValueFloatClampCopy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src)
967 {
968 int width = dst.getWidth();
969 int height = dst.getHeight();
970 int depth = dst.getDepth();
971
972 DE_ASSERT(src.getWidth() == width && src.getHeight() == height && src.getDepth() == depth);
973
974 // clamping copy
975 for (int z = 0; z < depth; z++)
976 for (int y = 0; y < height; y++)
977 for (int x = 0; x < width; x++)
978 {
979 const Vec4 data = src.getPixel(x, y, z);
980 dst.setPixel(Vec4(de::clamp(data.x(), 0.0f, 1.0f), data.y(), data.z(), data.w()), x, y, z);
981 }
982 }
983
texImage1D(deUint32 target,int level,deUint32 internalFormat,int width,int border,deUint32 format,deUint32 type,const void * data)984 void ReferenceContext::texImage1D (deUint32 target, int level, deUint32 internalFormat, int width, int border, deUint32 format, deUint32 type, const void* data)
985 {
986 texImage2D(target, level, internalFormat, width, 1, border, format, type, data);
987 }
988
texImage2D(deUint32 target,int level,deUint32 internalFormat,int width,int height,int border,deUint32 format,deUint32 type,const void * data)989 void ReferenceContext::texImage2D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int border, deUint32 format, deUint32 type, const void* data)
990 {
991 texImage3D(target, level, internalFormat, width, height, 1, border, format, type, data);
992 }
993
texImage3D(deUint32 target,int level,deUint32 internalFormat,int width,int height,int depth,int border,deUint32 format,deUint32 type,const void * data)994 void ReferenceContext::texImage3D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int depth, int border, deUint32 format, deUint32 type, const void* data)
995 {
996 TextureUnit& unit = m_textureUnits[m_activeTexture];
997 const void* unpackPtr = getPixelUnpackPtr(data);
998 const bool isDstFloatDepthFormat = (internalFormat == GL_DEPTH_COMPONENT32F || internalFormat == GL_DEPTH32F_STENCIL8); // depth components are limited to [0,1] range
999 TextureFormat storageFmt;
1000 TextureFormat transferFmt;
1001
1002 RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1003 RC_IF_ERROR(width < 0 || height < 0 || depth < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1004
1005 // Map storage format.
1006 storageFmt = mapInternalFormat(internalFormat);
1007 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1008 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1009
1010 // Map transfer format.
1011 transferFmt = glu::mapGLTransferFormat(format, type);
1012 RC_IF_ERROR(transferFmt.order == TextureFormat::CHANNELORDER_LAST ||
1013 transferFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1014
1015 if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
1016 {
1017 // Validate size and level.
1018 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height != 1 || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1019 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1020
1021 Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;
1022
1023 if (texture->isImmutable())
1024 {
1025 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1026
1027 ConstPixelBufferAccess dst(texture->getLevel(level));
1028 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1029 width != dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
1030 }
1031 else
1032 texture->allocLevel(level, storageFmt, width);
1033
1034 if (unpackPtr)
1035 {
1036 ConstPixelBufferAccess src = getUnpack2DAccess(transferFmt, width, 1, unpackPtr);
1037 PixelBufferAccess dst (texture->getLevel(level));
1038
1039 if (isDstFloatDepthFormat)
1040 depthValueFloatClampCopy(dst, src);
1041 else
1042 tcu::copy(dst, src);
1043 }
1044 else
1045 {
1046 // No data supplied, clear to black.
1047 PixelBufferAccess dst = texture->getLevel(level);
1048 tcu::clear(dst, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1049 }
1050 }
1051 else if (target == GL_TEXTURE_2D)
1052 {
1053 // Validate size and level.
1054 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1055 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1056
1057 Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;
1058
1059 if (texture->isImmutable())
1060 {
1061 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1062
1063 ConstPixelBufferAccess dst(texture->getLevel(level));
1064 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1065 width != dst.getWidth() ||
1066 height != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1067 }
1068 else
1069 texture->allocLevel(level, storageFmt, width, height);
1070
1071 if (unpackPtr)
1072 {
1073 ConstPixelBufferAccess src = getUnpack2DAccess(transferFmt, width, height, unpackPtr);
1074 PixelBufferAccess dst (texture->getLevel(level));
1075
1076 if (isDstFloatDepthFormat)
1077 depthValueFloatClampCopy(dst, src);
1078 else
1079 tcu::copy(dst, src);
1080 }
1081 else
1082 {
1083 // No data supplied, clear to black.
1084 PixelBufferAccess dst = texture->getLevel(level);
1085 tcu::clear(dst, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1086 }
1087 }
1088 else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1089 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1090 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1091 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1092 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1093 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1094 {
1095 // Validate size and level.
1096 RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1097 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);
1098
1099 TextureCube* texture = unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
1100 tcu::CubeFace face = mapGLCubeFace(target);
1101
1102 if (texture->isImmutable())
1103 {
1104 RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);
1105
1106 ConstPixelBufferAccess dst(texture->getFace(level, face));
1107 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1108 width != dst.getWidth() ||
1109 height != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1110 }
1111 else
1112 texture->allocFace(level, face, storageFmt, width, height);
1113
1114 if (unpackPtr)
1115 {
1116 ConstPixelBufferAccess src = getUnpack2DAccess(transferFmt, width, height, unpackPtr);
1117 PixelBufferAccess dst (texture->getFace(level, face));
1118
1119 if (isDstFloatDepthFormat)
1120 depthValueFloatClampCopy(dst, src);
1121 else
1122 tcu::copy(dst, src);
1123 }
1124 else
1125 {
1126 // No data supplied, clear to black.
1127 PixelBufferAccess dst = texture->getFace(level, face);
1128 tcu::clear(dst, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1129 }
1130 }
1131 else if (target == GL_TEXTURE_2D_ARRAY)
1132 {
1133 // Validate size and level.
1134 RC_IF_ERROR(width > m_limits.maxTexture2DSize ||
1135 height > m_limits.maxTexture2DSize ||
1136 depth > m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1137 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1138
1139 Texture2DArray* texture = unit.tex2DArrayBinding ? unit.tex2DArrayBinding : &unit.default2DArrayTex;
1140
1141 if (texture->isImmutable())
1142 {
1143 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1144
1145 ConstPixelBufferAccess dst(texture->getLevel(level));
1146 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1147 width != dst.getWidth() ||
1148 height != dst.getHeight() ||
1149 depth != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1150 }
1151 else
1152 texture->allocLevel(level, storageFmt, width, height, depth);
1153
1154 if (unpackPtr)
1155 {
1156 ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1157 PixelBufferAccess dst (texture->getLevel(level));
1158
1159 if (isDstFloatDepthFormat)
1160 depthValueFloatClampCopy(dst, src);
1161 else
1162 tcu::copy(dst, src);
1163 }
1164 else
1165 {
1166 // No data supplied, clear to black.
1167 PixelBufferAccess dst = texture->getLevel(level);
1168 tcu::clear(dst, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1169 }
1170 }
1171 else if (target == GL_TEXTURE_3D)
1172 {
1173 // Validate size and level.
1174 RC_IF_ERROR(width > m_limits.maxTexture3DSize ||
1175 height > m_limits.maxTexture3DSize ||
1176 depth > m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
1177 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture3DSize), GL_INVALID_VALUE, RC_RET_VOID);
1178
1179 Texture3D* texture = unit.tex3DBinding ? unit.tex3DBinding : &unit.default3DTex;
1180
1181 if (texture->isImmutable())
1182 {
1183 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1184
1185 ConstPixelBufferAccess dst(texture->getLevel(level));
1186 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1187 width != dst.getWidth() ||
1188 height != dst.getHeight() ||
1189 depth != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1190 }
1191 else
1192 texture->allocLevel(level, storageFmt, width, height, depth);
1193
1194 if (unpackPtr)
1195 {
1196 ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1197 PixelBufferAccess dst (texture->getLevel(level));
1198
1199 if (isDstFloatDepthFormat)
1200 depthValueFloatClampCopy(dst, src);
1201 else
1202 tcu::copy(dst, src);
1203 }
1204 else
1205 {
1206 // No data supplied, clear to black.
1207 PixelBufferAccess dst = texture->getLevel(level);
1208 tcu::clear(dst, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1209 }
1210 }
1211 else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1212 {
1213 // Validate size and level.
1214 RC_IF_ERROR(width != height ||
1215 width > m_limits.maxTexture2DSize ||
1216 depth % 6 != 0 ||
1217 depth > m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1218 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1219
1220 TextureCubeArray* texture = unit.texCubeArrayBinding ? unit.texCubeArrayBinding : &unit.defaultCubeArrayTex;
1221
1222 if (texture->isImmutable())
1223 {
1224 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1225
1226 ConstPixelBufferAccess dst(texture->getLevel(level));
1227 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1228 width != dst.getWidth() ||
1229 height != dst.getHeight() ||
1230 depth != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1231 }
1232 else
1233 texture->allocLevel(level, storageFmt, width, height, depth);
1234
1235 if (unpackPtr)
1236 {
1237 ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1238 PixelBufferAccess dst (texture->getLevel(level));
1239
1240 if (isDstFloatDepthFormat)
1241 depthValueFloatClampCopy(dst, src);
1242 else
1243 tcu::copy(dst, src);
1244 }
1245 else
1246 {
1247 // No data supplied, clear to black.
1248 PixelBufferAccess dst = texture->getLevel(level);
1249 tcu::clear(dst, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1250 }
1251 }
1252 else
1253 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1254 }
1255
texSubImage1D(deUint32 target,int level,int xoffset,int width,deUint32 format,deUint32 type,const void * data)1256 void ReferenceContext::texSubImage1D (deUint32 target, int level, int xoffset, int width, deUint32 format, deUint32 type, const void* data)
1257 {
1258 texSubImage2D(target, level, xoffset, 0, width, 1, format, type, data);
1259 }
1260
texSubImage2D(deUint32 target,int level,int xoffset,int yoffset,int width,int height,deUint32 format,deUint32 type,const void * data)1261 void ReferenceContext::texSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int width, int height, deUint32 format, deUint32 type, const void* data)
1262 {
1263 texSubImage3D(target, level, xoffset, yoffset, 0, width, height, 1, format, type, data);
1264 }
1265
texSubImage3D(deUint32 target,int level,int xoffset,int yoffset,int zoffset,int width,int height,int depth,deUint32 format,deUint32 type,const void * data)1266 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)
1267 {
1268 TextureUnit& unit = m_textureUnits[m_activeTexture];
1269
1270 RC_IF_ERROR(xoffset < 0 || yoffset < 0 || zoffset < 0, GL_INVALID_VALUE, RC_RET_VOID);
1271 RC_IF_ERROR(width < 0 || height < 0 || depth < 0, GL_INVALID_VALUE, RC_RET_VOID);
1272
1273 TextureFormat transferFmt = glu::mapGLTransferFormat(format, type);
1274 RC_IF_ERROR(transferFmt.order == TextureFormat::CHANNELORDER_LAST ||
1275 transferFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1276
1277 ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, getPixelUnpackPtr(data));
1278
1279 if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
1280 {
1281 Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;
1282
1283 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1284
1285 PixelBufferAccess dst = texture.getLevel(level);
1286
1287 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1288 yoffset + height > dst.getHeight() ||
1289 zoffset + depth > dst.getDepth(),
1290 GL_INVALID_VALUE, RC_RET_VOID);
1291
1292 // depth components are limited to [0,1] range
1293 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1294 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1295 else
1296 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1297 }
1298 else if (target == GL_TEXTURE_2D)
1299 {
1300 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1301
1302 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1303
1304 PixelBufferAccess dst = texture.getLevel(level);
1305
1306 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1307 yoffset + height > dst.getHeight() ||
1308 zoffset + depth > dst.getDepth(),
1309 GL_INVALID_VALUE, RC_RET_VOID);
1310
1311 // depth components are limited to [0,1] range
1312 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1313 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1314 else
1315 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1316 }
1317 else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1318 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1319 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1320 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1321 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1322 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1323 {
1324 TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1325 tcu::CubeFace face = mapGLCubeFace(target);
1326
1327 RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);
1328
1329 PixelBufferAccess dst = texture.getFace(level, face);
1330
1331 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1332 yoffset + height > dst.getHeight() ||
1333 zoffset + depth > dst.getDepth(),
1334 GL_INVALID_VALUE, RC_RET_VOID);
1335
1336 // depth components are limited to [0,1] range
1337 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1338 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1339 else
1340 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1341 }
1342 else if (target == GL_TEXTURE_3D)
1343 {
1344 Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;
1345
1346 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1347
1348 PixelBufferAccess dst = texture.getLevel(level);
1349
1350 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1351 yoffset + height > dst.getHeight() ||
1352 zoffset + depth > dst.getDepth(),
1353 GL_INVALID_VALUE, RC_RET_VOID);
1354
1355 // depth components are limited to [0,1] range
1356 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1357 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1358 else
1359 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1360 }
1361 else if (target == GL_TEXTURE_2D_ARRAY)
1362 {
1363 Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;
1364
1365 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1366
1367 PixelBufferAccess dst = texture.getLevel(level);
1368
1369 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1370 yoffset + height > dst.getHeight() ||
1371 zoffset + depth > dst.getDepth(),
1372 GL_INVALID_VALUE, RC_RET_VOID);
1373
1374 // depth components are limited to [0,1] range
1375 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1376 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1377 else
1378 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1379 }
1380 else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1381 {
1382 TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;
1383
1384 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1385
1386 PixelBufferAccess dst = texture.getLevel(level);
1387
1388 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1389 yoffset + height > dst.getHeight() ||
1390 zoffset + depth > dst.getDepth(),
1391 GL_INVALID_VALUE, RC_RET_VOID);
1392
1393 // depth components are limited to [0,1] range
1394 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1395 depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1396 else
1397 tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1398 }
1399 else
1400 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1401 }
1402
copyTexImage1D(deUint32 target,int level,deUint32 internalFormat,int x,int y,int width,int border)1403 void ReferenceContext::copyTexImage1D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int border)
1404 {
1405 TextureUnit& unit = m_textureUnits[m_activeTexture];
1406 TextureFormat storageFmt;
1407 rr::MultisampleConstPixelBufferAccess src = getReadColorbuffer();
1408
1409 RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1410 RC_IF_ERROR(width < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1411 RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1412
1413 // Map storage format.
1414 storageFmt = mapInternalFormat(internalFormat);
1415 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1416 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1417
1418 if (target == GL_TEXTURE_1D)
1419 {
1420 // Validate size and level.
1421 RC_IF_ERROR(width > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1422 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1423
1424 Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;
1425
1426 if (texture->isImmutable())
1427 {
1428 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1429
1430 ConstPixelBufferAccess dst(texture->getLevel(level));
1431 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1432 width != dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
1433 }
1434 else
1435 texture->allocLevel(level, storageFmt, width);
1436
1437 // Copy from current framebuffer.
1438 PixelBufferAccess dst = texture->getLevel(level);
1439 for (int xo = 0; xo < width; xo++)
1440 {
1441 if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
1442 continue; // Undefined pixel.
1443
1444 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo, 0);
1445 }
1446 }
1447 else
1448 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1449 }
1450
copyTexImage2D(deUint32 target,int level,deUint32 internalFormat,int x,int y,int width,int height,int border)1451 void ReferenceContext::copyTexImage2D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int height, int border)
1452 {
1453 TextureUnit& unit = m_textureUnits[m_activeTexture];
1454 TextureFormat storageFmt;
1455 rr::MultisampleConstPixelBufferAccess src = getReadColorbuffer();
1456
1457 RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1458 RC_IF_ERROR(width < 0 || height < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1459 RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1460
1461 // Map storage format.
1462 storageFmt = mapInternalFormat(internalFormat);
1463 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1464 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1465
1466 if (target == GL_TEXTURE_2D)
1467 {
1468 // Validate size and level.
1469 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1470 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1471
1472 Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;
1473
1474 if (texture->isImmutable())
1475 {
1476 RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1477
1478 ConstPixelBufferAccess dst(texture->getLevel(level));
1479 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1480 width != dst.getWidth() ||
1481 height != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1482 }
1483 else
1484 texture->allocLevel(level, storageFmt, width, height);
1485
1486 // Copy from current framebuffer.
1487 PixelBufferAccess dst = texture->getLevel(level);
1488 for (int yo = 0; yo < height; yo++)
1489 for (int xo = 0; xo < width; xo++)
1490 {
1491 if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1492 continue; // Undefined pixel.
1493
1494 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
1495 }
1496 }
1497 else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1498 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1499 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1500 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1501 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1502 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1503 {
1504 // Validate size and level.
1505 RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
1506 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);
1507
1508 TextureCube* texture = unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
1509 tcu::CubeFace face = mapGLCubeFace(target);
1510
1511 if (texture->isImmutable())
1512 {
1513 RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);
1514
1515 ConstPixelBufferAccess dst(texture->getFace(level, face));
1516 RC_IF_ERROR(storageFmt != dst.getFormat() ||
1517 width != dst.getWidth() ||
1518 height != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1519 }
1520 else
1521 texture->allocFace(level, face, storageFmt, width, height);
1522
1523 // Copy from current framebuffer.
1524 PixelBufferAccess dst = texture->getFace(level, face);
1525 for (int yo = 0; yo < height; yo++)
1526 for (int xo = 0; xo < width; xo++)
1527 {
1528 if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1529 continue; // Undefined pixel.
1530
1531 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
1532 }
1533 }
1534 else
1535 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1536 }
1537
copyTexSubImage1D(deUint32 target,int level,int xoffset,int x,int y,int width)1538 void ReferenceContext::copyTexSubImage1D (deUint32 target, int level, int xoffset, int x, int y, int width)
1539 {
1540 TextureUnit& unit = m_textureUnits[m_activeTexture];
1541 rr::MultisampleConstPixelBufferAccess src = getReadColorbuffer();
1542
1543 RC_IF_ERROR(xoffset < 0, GL_INVALID_VALUE, RC_RET_VOID);
1544 RC_IF_ERROR(width < 0, GL_INVALID_VALUE, RC_RET_VOID);
1545 RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1546
1547 if (target == GL_TEXTURE_1D)
1548 {
1549 Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;
1550
1551 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1552
1553 PixelBufferAccess dst = texture.getLevel(level);
1554
1555 RC_IF_ERROR(xoffset + width > dst.getWidth(), GL_INVALID_VALUE, RC_RET_VOID);
1556
1557 for (int xo = 0; xo < width; xo++)
1558 {
1559 if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
1560 continue;
1561
1562 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo+xoffset, 0);
1563 }
1564 }
1565 else
1566 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1567 }
1568
copyTexSubImage2D(deUint32 target,int level,int xoffset,int yoffset,int x,int y,int width,int height)1569 void ReferenceContext::copyTexSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int x, int y, int width, int height)
1570 {
1571 TextureUnit& unit = m_textureUnits[m_activeTexture];
1572 rr::MultisampleConstPixelBufferAccess src = getReadColorbuffer();
1573
1574 RC_IF_ERROR(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE, RC_RET_VOID);
1575 RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
1576 RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1577
1578 if (target == GL_TEXTURE_2D)
1579 {
1580 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1581
1582 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1583
1584 PixelBufferAccess dst = texture.getLevel(level);
1585
1586 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1587 yoffset + height > dst.getHeight(),
1588 GL_INVALID_VALUE, RC_RET_VOID);
1589
1590 for (int yo = 0; yo < height; yo++)
1591 for (int xo = 0; xo < width; xo++)
1592 {
1593 if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1594 continue;
1595
1596 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
1597 }
1598 }
1599 else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1600 target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1601 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1602 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1603 target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1604 target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1605 {
1606 TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1607 tcu::CubeFace face = mapGLCubeFace(target);
1608
1609 RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);
1610
1611 PixelBufferAccess dst = texture.getFace(level, face);
1612
1613 RC_IF_ERROR(xoffset + width > dst.getWidth() ||
1614 yoffset + height > dst.getHeight(),
1615 GL_INVALID_VALUE, RC_RET_VOID);
1616
1617 for (int yo = 0; yo < height; yo++)
1618 for (int xo = 0; xo < width; xo++)
1619 {
1620 if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1621 continue;
1622
1623 dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
1624 }
1625 }
1626 else
1627 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1628 }
1629
copyTexSubImage3D(deUint32 target,int level,int xoffset,int yoffset,int zoffset,int x,int y,int width,int height)1630 void ReferenceContext::copyTexSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height)
1631 {
1632 DE_UNREF(target && level && xoffset && yoffset && zoffset && x && y && width && height);
1633 DE_ASSERT(false);
1634 }
1635
texStorage2D(deUint32 target,int levels,deUint32 internalFormat,int width,int height)1636 void ReferenceContext::texStorage2D (deUint32 target, int levels, deUint32 internalFormat, int width, int height)
1637 {
1638 TextureUnit& unit = m_textureUnits[m_activeTexture];
1639 TextureFormat storageFmt;
1640
1641 RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
1642 RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);
1643
1644 // Map storage format.
1645 storageFmt = mapInternalFormat(internalFormat);
1646 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1647 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1648
1649 if (target == GL_TEXTURE_2D)
1650 {
1651 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1652
1653 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height >= m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1654 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1655
1656 texture.clearLevels();
1657 texture.setImmutable();
1658
1659 for (int level = 0; level < levels; level++)
1660 {
1661 int levelW = de::max(1, width >> level);
1662 int levelH = de::max(1, height >> level);
1663
1664 texture.allocLevel(level, storageFmt, levelW, levelH);
1665 }
1666 }
1667 else if (target == GL_TEXTURE_CUBE_MAP)
1668 {
1669 TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1670
1671 RC_IF_ERROR(width > m_limits.maxTextureCubeSize || height > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
1672 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1673
1674 texture.clearLevels();
1675 texture.setImmutable();
1676
1677 for (int level = 0; level < levels; level++)
1678 {
1679 int levelW = de::max(1, width >> level);
1680 int levelH = de::max(1, height >> level);
1681
1682 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1683 texture.allocFace(level, (tcu::CubeFace)face, storageFmt, levelW, levelH);
1684 }
1685 }
1686 else
1687 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1688 }
1689
texStorage3D(deUint32 target,int levels,deUint32 internalFormat,int width,int height,int depth)1690 void ReferenceContext::texStorage3D (deUint32 target, int levels, deUint32 internalFormat, int width, int height, int depth)
1691 {
1692 TextureUnit& unit = m_textureUnits[m_activeTexture];
1693 TextureFormat storageFmt;
1694
1695 RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
1696 RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);
1697
1698 // Map storage format.
1699 storageFmt = mapInternalFormat(internalFormat);
1700 RC_IF_ERROR(storageFmt.order == TextureFormat::CHANNELORDER_LAST ||
1701 storageFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1702
1703 if (target == GL_TEXTURE_2D_ARRAY)
1704 {
1705 Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;
1706
1707 RC_IF_ERROR(width > m_limits.maxTexture2DSize ||
1708 height >= m_limits.maxTexture2DSize ||
1709 depth >= m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1710 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1711
1712 texture.clearLevels();
1713 texture.setImmutable();
1714
1715 for (int level = 0; level < levels; level++)
1716 {
1717 int levelW = de::max(1, width >> level);
1718 int levelH = de::max(1, height >> level);
1719
1720 texture.allocLevel(level, storageFmt, levelW, levelH, depth);
1721 }
1722 }
1723 else if (target == GL_TEXTURE_3D)
1724 {
1725 Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;
1726
1727 RC_IF_ERROR(width > m_limits.maxTexture3DSize ||
1728 height > m_limits.maxTexture3DSize ||
1729 depth > m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
1730 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1731
1732 texture.clearLevels();
1733 texture.setImmutable();
1734
1735 for (int level = 0; level < levels; level++)
1736 {
1737 int levelW = de::max(1, width >> level);
1738 int levelH = de::max(1, height >> level);
1739 int levelD = de::max(1, depth >> level);
1740
1741 texture.allocLevel(level, storageFmt, levelW, levelH, levelD);
1742 }
1743 }
1744 else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1745 {
1746 TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;
1747
1748 RC_IF_ERROR(width != height ||
1749 depth % 6 != 0 ||
1750 width > m_limits.maxTexture2DSize ||
1751 depth >= m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1752 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1753
1754 texture.clearLevels();
1755 texture.setImmutable();
1756
1757 for (int level = 0; level < levels; level++)
1758 {
1759 int levelW = de::max(1, width >> level);
1760 int levelH = de::max(1, height >> level);
1761
1762 texture.allocLevel(level, storageFmt, levelW, levelH, depth);
1763 }
1764 }
1765 else
1766 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1767 }
1768
1769 // \todo [2014-02-19 pyry] Duplicated with code in gluTextureUtil.hpp
1770
mapGLWrapMode(int value)1771 static inline tcu::Sampler::WrapMode mapGLWrapMode (int value)
1772 {
1773 switch (value)
1774 {
1775 case GL_CLAMP_TO_EDGE: return tcu::Sampler::CLAMP_TO_EDGE;
1776 case GL_REPEAT: return tcu::Sampler::REPEAT_GL;
1777 case GL_MIRRORED_REPEAT: return tcu::Sampler::MIRRORED_REPEAT_GL;
1778 default: return tcu::Sampler::WRAPMODE_LAST;
1779 }
1780 }
1781
mapGLFilterMode(int value)1782 static inline tcu::Sampler::FilterMode mapGLFilterMode (int value)
1783 {
1784 switch (value)
1785 {
1786 case GL_NEAREST: return tcu::Sampler::NEAREST;
1787 case GL_LINEAR: return tcu::Sampler::LINEAR;
1788 case GL_NEAREST_MIPMAP_NEAREST: return tcu::Sampler::NEAREST_MIPMAP_NEAREST;
1789 case GL_NEAREST_MIPMAP_LINEAR: return tcu::Sampler::NEAREST_MIPMAP_LINEAR;
1790 case GL_LINEAR_MIPMAP_NEAREST: return tcu::Sampler::LINEAR_MIPMAP_NEAREST;
1791 case GL_LINEAR_MIPMAP_LINEAR: return tcu::Sampler::LINEAR_MIPMAP_LINEAR;
1792 default: return tcu::Sampler::FILTERMODE_LAST;
1793 }
1794 }
1795
texParameteri(deUint32 target,deUint32 pname,int value)1796 void ReferenceContext::texParameteri (deUint32 target, deUint32 pname, int value)
1797 {
1798 TextureUnit& unit = m_textureUnits[m_activeTexture];
1799 Texture* texture = DE_NULL;
1800
1801 switch (target)
1802 {
1803 case GL_TEXTURE_1D: texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex; break;
1804 case GL_TEXTURE_2D: texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex; break;
1805 case GL_TEXTURE_CUBE_MAP: texture = unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex; break;
1806 case GL_TEXTURE_2D_ARRAY: texture = unit.tex2DArrayBinding ? unit.tex2DArrayBinding : &unit.default2DArrayTex; break;
1807 case GL_TEXTURE_3D: texture = unit.tex3DBinding ? unit.tex3DBinding : &unit.default3DTex; break;
1808 case GL_TEXTURE_CUBE_MAP_ARRAY: texture = unit.texCubeArrayBinding ? unit.texCubeArrayBinding : &unit.defaultCubeArrayTex; break;
1809
1810 default: RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1811 }
1812
1813 switch (pname)
1814 {
1815 case GL_TEXTURE_WRAP_S:
1816 {
1817 tcu::Sampler::WrapMode wrapS = mapGLWrapMode(value);
1818 RC_IF_ERROR(wrapS == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1819 texture->getSampler().wrapS = wrapS;
1820 break;
1821 }
1822
1823 case GL_TEXTURE_WRAP_T:
1824 {
1825 tcu::Sampler::WrapMode wrapT = mapGLWrapMode(value);
1826 RC_IF_ERROR(wrapT == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1827 texture->getSampler().wrapT = wrapT;
1828 break;
1829 }
1830
1831 case GL_TEXTURE_WRAP_R:
1832 {
1833 tcu::Sampler::WrapMode wrapR = mapGLWrapMode(value);
1834 RC_IF_ERROR(wrapR == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1835 texture->getSampler().wrapR = wrapR;
1836 break;
1837 }
1838
1839 case GL_TEXTURE_MIN_FILTER:
1840 {
1841 tcu::Sampler::FilterMode minMode = mapGLFilterMode(value);
1842 RC_IF_ERROR(minMode == tcu::Sampler::FILTERMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1843 texture->getSampler().minFilter = minMode;
1844 break;
1845 }
1846
1847 case GL_TEXTURE_MAG_FILTER:
1848 {
1849 tcu::Sampler::FilterMode magMode = mapGLFilterMode(value);
1850 RC_IF_ERROR(magMode != tcu::Sampler::LINEAR && magMode != tcu::Sampler::NEAREST,
1851 GL_INVALID_VALUE, RC_RET_VOID);
1852 texture->getSampler().magFilter = magMode;
1853 break;
1854 }
1855
1856 case GL_TEXTURE_MAX_LEVEL:
1857 {
1858 RC_IF_ERROR(value < 0, GL_INVALID_VALUE, RC_RET_VOID);
1859 texture->setMaxLevel(value);
1860 break;
1861 }
1862
1863 default:
1864 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1865 }
1866 }
1867
mapGLAttachmentPoint(deUint32 attachment)1868 static inline Framebuffer::AttachmentPoint mapGLAttachmentPoint (deUint32 attachment)
1869 {
1870 switch (attachment)
1871 {
1872 case GL_COLOR_ATTACHMENT0: return Framebuffer::ATTACHMENTPOINT_COLOR0;
1873 case GL_DEPTH_ATTACHMENT: return Framebuffer::ATTACHMENTPOINT_DEPTH;
1874 case GL_STENCIL_ATTACHMENT: return Framebuffer::ATTACHMENTPOINT_STENCIL;
1875 default: return Framebuffer::ATTACHMENTPOINT_LAST;
1876 }
1877 }
1878
mapGLFboTexTarget(deUint32 target)1879 static inline Framebuffer::TexTarget mapGLFboTexTarget (deUint32 target)
1880 {
1881 switch (target)
1882 {
1883 case GL_TEXTURE_2D: return Framebuffer::TEXTARGET_2D;
1884 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X;
1885 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y;
1886 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z;
1887 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X;
1888 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y;
1889 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z;
1890 default: return Framebuffer::TEXTARGET_LAST;
1891 }
1892 }
1893
acquireFboAttachmentReference(const Framebuffer::Attachment & attachment)1894 void ReferenceContext::acquireFboAttachmentReference (const Framebuffer::Attachment& attachment)
1895 {
1896 switch (attachment.type)
1897 {
1898 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
1899 {
1900 TCU_CHECK(attachment.name != 0);
1901 Texture* texture = m_textures.find(attachment.name);
1902 TCU_CHECK(texture);
1903 m_textures.acquireReference(texture);
1904 break;
1905 }
1906
1907 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
1908 {
1909 TCU_CHECK(attachment.name != 0);
1910 Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
1911 TCU_CHECK(rbo);
1912 m_renderbuffers.acquireReference(rbo);
1913 break;
1914 }
1915
1916 default:
1917 break; // Silently ignore
1918 }
1919 }
1920
releaseFboAttachmentReference(const Framebuffer::Attachment & attachment)1921 void ReferenceContext::releaseFboAttachmentReference (const Framebuffer::Attachment& attachment)
1922 {
1923 switch (attachment.type)
1924 {
1925 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
1926 {
1927 TCU_CHECK(attachment.name != 0);
1928 Texture* texture = m_textures.find(attachment.name);
1929 TCU_CHECK(texture);
1930 m_textures.releaseReference(texture);
1931 break;
1932 }
1933
1934 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
1935 {
1936 TCU_CHECK(attachment.name != 0);
1937 Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
1938 TCU_CHECK(rbo);
1939 m_renderbuffers.releaseReference(rbo);
1940 break;
1941 }
1942
1943 default:
1944 break; // Silently ignore
1945 }
1946 }
1947
framebufferTexture2D(deUint32 target,deUint32 attachment,deUint32 textarget,deUint32 texture,int level)1948 void ReferenceContext::framebufferTexture2D (deUint32 target, deUint32 attachment, deUint32 textarget, deUint32 texture, int level)
1949 {
1950 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
1951 {
1952 // Attach to both depth and stencil.
1953 framebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textarget, texture, level);
1954 framebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textarget, texture, level);
1955 }
1956 else
1957 {
1958 Framebuffer::AttachmentPoint point = mapGLAttachmentPoint(attachment);
1959 Texture* texObj = DE_NULL;
1960 Framebuffer::TexTarget fboTexTarget = mapGLFboTexTarget(textarget);
1961
1962 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
1963 target != GL_DRAW_FRAMEBUFFER &&
1964 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
1965 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1966
1967 // Select binding point.
1968 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
1969 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
1970
1971 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
1972 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
1973 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
1974
1975 if (texture != 0)
1976 {
1977 texObj = m_textures.find(texture);
1978
1979 RC_IF_ERROR(!texObj, GL_INVALID_OPERATION, RC_RET_VOID);
1980 RC_IF_ERROR(level != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.
1981
1982 if (texObj->getType() == Texture::TYPE_2D)
1983 RC_IF_ERROR(fboTexTarget != Framebuffer::TEXTARGET_2D, GL_INVALID_OPERATION, RC_RET_VOID);
1984 else
1985 {
1986 TCU_CHECK(texObj->getType() == Texture::TYPE_CUBE_MAP);
1987 if (!deInRange32(fboTexTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X, Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
1988 RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
1989 }
1990 }
1991
1992 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
1993 for (int ndx = 0; ndx < bindingRefCount; ndx++)
1994 releaseFboAttachmentReference(fboAttachment);
1995 fboAttachment = Framebuffer::Attachment();
1996
1997 if (texObj)
1998 {
1999 fboAttachment.type = Framebuffer::ATTACHMENTTYPE_TEXTURE;
2000 fboAttachment.name = texObj->getName();
2001 fboAttachment.texTarget = fboTexTarget;
2002 fboAttachment.level = level;
2003
2004 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2005 acquireFboAttachmentReference(fboAttachment);
2006 }
2007 }
2008 }
2009
framebufferTextureLayer(deUint32 target,deUint32 attachment,deUint32 texture,int level,int layer)2010 void ReferenceContext::framebufferTextureLayer (deUint32 target, deUint32 attachment, deUint32 texture, int level, int layer)
2011 {
2012 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
2013 {
2014 // Attach to both depth and stencil.
2015 framebufferTextureLayer(target, GL_DEPTH_ATTACHMENT, texture, level, layer);
2016 framebufferTextureLayer(target, GL_STENCIL_ATTACHMENT, texture, level, layer);
2017 }
2018 else
2019 {
2020 Framebuffer::AttachmentPoint point = mapGLAttachmentPoint(attachment);
2021 Texture* texObj = DE_NULL;
2022
2023 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
2024 target != GL_DRAW_FRAMEBUFFER &&
2025 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2026 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2027
2028 // Select binding point.
2029 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2030 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2031
2032 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2033 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2034 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2035
2036 if (texture != 0)
2037 {
2038 texObj = m_textures.find(texture);
2039
2040 RC_IF_ERROR(!texObj, GL_INVALID_OPERATION, RC_RET_VOID);
2041 RC_IF_ERROR(level != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.
2042
2043 RC_IF_ERROR(texObj->getType() != Texture::TYPE_2D_ARRAY &&
2044 texObj->getType() != Texture::TYPE_3D &&
2045 texObj->getType() != Texture::TYPE_CUBE_MAP_ARRAY, GL_INVALID_OPERATION, RC_RET_VOID);
2046
2047 if (texObj->getType() == Texture::TYPE_2D_ARRAY || texObj->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2048 {
2049 RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_ARRAY_TEXTURE_LAYERS), GL_INVALID_VALUE, RC_RET_VOID);
2050 RC_IF_ERROR((level < 0) || (level > tcu::log2(GL_MAX_TEXTURE_SIZE)), GL_INVALID_VALUE, RC_RET_VOID);
2051 }
2052 else if (texObj->getType() == Texture::TYPE_3D)
2053 {
2054 RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_3D_TEXTURE_SIZE), GL_INVALID_VALUE, RC_RET_VOID);
2055 RC_IF_ERROR((level < 0) || (level > tcu::log2(GL_MAX_3D_TEXTURE_SIZE)), GL_INVALID_VALUE, RC_RET_VOID);
2056 }
2057 }
2058
2059 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2060 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2061 releaseFboAttachmentReference(fboAttachment);
2062 fboAttachment = Framebuffer::Attachment();
2063
2064 if (texObj)
2065 {
2066 fboAttachment.type = Framebuffer::ATTACHMENTTYPE_TEXTURE;
2067 fboAttachment.name = texObj->getName();
2068 fboAttachment.texTarget = texLayeredTypeToTarget(texObj->getType());
2069 fboAttachment.level = level;
2070 fboAttachment.layer = layer;
2071
2072 DE_ASSERT(fboAttachment.texTarget != Framebuffer::TEXTARGET_LAST);
2073
2074 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2075 acquireFboAttachmentReference(fboAttachment);
2076 }
2077 }
2078 }
2079
framebufferRenderbuffer(deUint32 target,deUint32 attachment,deUint32 renderbuffertarget,deUint32 renderbuffer)2080 void ReferenceContext::framebufferRenderbuffer (deUint32 target, deUint32 attachment, deUint32 renderbuffertarget, deUint32 renderbuffer)
2081 {
2082 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
2083 {
2084 // Attach both to depth and stencil.
2085 framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, renderbuffer);
2086 framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, renderbuffer);
2087 }
2088 else
2089 {
2090 Framebuffer::AttachmentPoint point = mapGLAttachmentPoint(attachment);
2091 Renderbuffer* rbo = DE_NULL;
2092
2093 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
2094 target != GL_DRAW_FRAMEBUFFER &&
2095 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2096 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2097
2098 // Select binding point.
2099 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2100 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2101
2102 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2103 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2104 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2105
2106 if (renderbuffer != 0)
2107 {
2108 rbo = m_renderbuffers.find(renderbuffer);
2109
2110 RC_IF_ERROR(renderbuffertarget != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2111 RC_IF_ERROR(!rbo, GL_INVALID_OPERATION, RC_RET_VOID);
2112 }
2113
2114 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2115 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2116 releaseFboAttachmentReference(fboAttachment);
2117 fboAttachment = Framebuffer::Attachment();
2118
2119 if (rbo)
2120 {
2121 fboAttachment.type = Framebuffer::ATTACHMENTTYPE_RENDERBUFFER;
2122 fboAttachment.name = rbo->getName();
2123
2124 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2125 acquireFboAttachmentReference(fboAttachment);
2126 }
2127 }
2128 }
2129
checkFramebufferStatus(deUint32 target)2130 deUint32 ReferenceContext::checkFramebufferStatus (deUint32 target)
2131 {
2132 RC_IF_ERROR(target != GL_FRAMEBUFFER &&
2133 target != GL_DRAW_FRAMEBUFFER &&
2134 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, 0);
2135
2136 // Select binding point.
2137 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2138
2139 // Default framebuffer is always complete.
2140 if (!framebufferBinding)
2141 return GL_FRAMEBUFFER_COMPLETE;
2142
2143 int width = -1;
2144 int height = -1;
2145 bool hasAttachment = false;
2146 bool attachmentComplete = true;
2147 bool dimensionsOk = true;
2148
2149 for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
2150 {
2151 const Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
2152 int attachmentWidth = 0;
2153 int attachmentHeight = 0;
2154 tcu::TextureFormat attachmentFormat;
2155
2156 if (attachment.type == Framebuffer::ATTACHMENTTYPE_TEXTURE)
2157 {
2158 const Texture* texture = m_textures.find(attachment.name);
2159 tcu::ConstPixelBufferAccess level;
2160 TCU_CHECK(texture);
2161
2162 if (attachment.texTarget == Framebuffer::TEXTARGET_2D)
2163 {
2164 DE_ASSERT(texture->getType() == Texture::TYPE_2D);
2165 const Texture2D* tex2D = static_cast<const Texture2D*>(texture);
2166
2167 if (tex2D->hasLevel(attachment.level))
2168 level = tex2D->getLevel(attachment.level);
2169 }
2170 else if (deInRange32(attachment.texTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X,
2171 Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
2172 {
2173 DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP);
2174
2175 const TextureCube* texCube = static_cast<const TextureCube*>(texture);
2176 const tcu::CubeFace face = texTargetToFace(attachment.texTarget);
2177 TCU_CHECK(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
2178
2179 if (texCube->hasFace(attachment.level, face))
2180 level = texCube->getFace(attachment.level, face);
2181 }
2182 else if (attachment.texTarget == Framebuffer::TEXTARGET_2D_ARRAY)
2183 {
2184 DE_ASSERT(texture->getType() == Texture::TYPE_2D_ARRAY);
2185 const Texture2DArray* tex2DArr = static_cast<const Texture2DArray*>(texture);
2186
2187 if (tex2DArr->hasLevel(attachment.level))
2188 level = tex2DArr->getLevel(attachment.level); // \note Slice doesn't matter here.
2189 }
2190 else if (attachment.texTarget == Framebuffer::TEXTARGET_3D)
2191 {
2192 DE_ASSERT(texture->getType() == Texture::TYPE_3D);
2193 const Texture3D* tex3D = static_cast<const Texture3D*>(texture);
2194
2195 if (tex3D->hasLevel(attachment.level))
2196 level = tex3D->getLevel(attachment.level); // \note Slice doesn't matter here.
2197 }
2198 else if (attachment.texTarget == Framebuffer::TEXTARGET_CUBE_MAP_ARRAY)
2199 {
2200 DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY);
2201 const TextureCubeArray* texCubeArr = static_cast<const TextureCubeArray*>(texture);
2202
2203 if (texCubeArr->hasLevel(attachment.level))
2204 level = texCubeArr->getLevel(attachment.level); // \note Slice doesn't matter here.
2205 }
2206 else
2207 TCU_FAIL("Framebuffer attached to a texture but no valid target specified");
2208
2209 attachmentWidth = level.getWidth();
2210 attachmentHeight = level.getHeight();
2211 attachmentFormat = level.getFormat();
2212 }
2213 else if (attachment.type == Framebuffer::ATTACHMENTTYPE_RENDERBUFFER)
2214 {
2215 const Renderbuffer* renderbuffer = m_renderbuffers.find(attachment.name);
2216 TCU_CHECK(renderbuffer);
2217
2218 attachmentWidth = renderbuffer->getWidth();
2219 attachmentHeight = renderbuffer->getHeight();
2220 attachmentFormat = renderbuffer->getFormat();
2221 }
2222 else
2223 {
2224 TCU_CHECK(attachment.type == Framebuffer::ATTACHMENTTYPE_LAST);
2225 continue; // Skip rest of checks.
2226 }
2227
2228 if (!hasAttachment && attachmentWidth > 0 && attachmentHeight > 0)
2229 {
2230 width = attachmentWidth;
2231 height = attachmentHeight;
2232 hasAttachment = true;
2233 }
2234 else if (attachmentWidth != width || attachmentHeight != height)
2235 dimensionsOk = false;
2236
2237 // Validate attachment point compatibility.
2238 switch (attachmentFormat.order)
2239 {
2240 case TextureFormat::R:
2241 case TextureFormat::RG:
2242 case TextureFormat::RGB:
2243 case TextureFormat::RGBA:
2244 case TextureFormat::sRGB:
2245 case TextureFormat::sRGBA:
2246 if (point != Framebuffer::ATTACHMENTPOINT_COLOR0)
2247 attachmentComplete = false;
2248 break;
2249
2250 case TextureFormat::D:
2251 if (point != Framebuffer::ATTACHMENTPOINT_DEPTH)
2252 attachmentComplete = false;
2253 break;
2254
2255 case TextureFormat::S:
2256 if (point != Framebuffer::ATTACHMENTPOINT_STENCIL)
2257 attachmentComplete = false;
2258 break;
2259
2260 case TextureFormat::DS:
2261 if (point != Framebuffer::ATTACHMENTPOINT_DEPTH &&
2262 point != Framebuffer::ATTACHMENTPOINT_STENCIL)
2263 attachmentComplete = false;
2264 break;
2265
2266 default:
2267 TCU_FAIL("Unsupported attachment channel order");
2268 }
2269 }
2270
2271 if (!attachmentComplete)
2272 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2273 else if (!hasAttachment)
2274 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
2275 else if (!dimensionsOk)
2276 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
2277 else
2278 return GL_FRAMEBUFFER_COMPLETE;
2279 }
2280
getFramebufferAttachmentParameteriv(deUint32 target,deUint32 attachment,deUint32 pname,int * params)2281 void ReferenceContext::getFramebufferAttachmentParameteriv (deUint32 target, deUint32 attachment, deUint32 pname, int* params)
2282 {
2283 DE_UNREF(target && attachment && pname && params);
2284 TCU_CHECK(false); // \todo [pyry] Implement
2285 }
2286
renderbufferStorage(deUint32 target,deUint32 internalformat,int width,int height)2287 void ReferenceContext::renderbufferStorage (deUint32 target, deUint32 internalformat, int width, int height)
2288 {
2289 TextureFormat format = glu::mapGLInternalFormat(internalformat);
2290
2291 RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2292 RC_IF_ERROR(!m_renderbufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2293 RC_IF_ERROR(!deInRange32(width, 0, m_limits.maxRenderbufferSize) ||
2294 !deInRange32(height, 0, m_limits.maxRenderbufferSize),
2295 GL_INVALID_OPERATION, RC_RET_VOID);
2296 RC_IF_ERROR(format.order == TextureFormat::CHANNELORDER_LAST ||
2297 format.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2298
2299 m_renderbufferBinding->setStorage(format, (int)width, (int)height);
2300 }
2301
renderbufferStorageMultisample(deUint32 target,int samples,deUint32 internalFormat,int width,int height)2302 void ReferenceContext::renderbufferStorageMultisample (deUint32 target, int samples, deUint32 internalFormat, int width, int height)
2303 {
2304 // \todo [2012-04-07 pyry] Implement MSAA support.
2305 DE_UNREF(samples);
2306 renderbufferStorage(target, internalFormat, width, height);
2307 }
2308
getFboAttachment(const rc::Framebuffer & framebuffer,rc::Framebuffer::AttachmentPoint point)2309 tcu::PixelBufferAccess ReferenceContext::getFboAttachment (const rc::Framebuffer& framebuffer, rc::Framebuffer::AttachmentPoint point)
2310 {
2311 const Framebuffer::Attachment& attachment = framebuffer.getAttachment(point);
2312
2313 switch (attachment.type)
2314 {
2315 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
2316 {
2317 Texture* texture = m_textures.find(attachment.name);
2318 TCU_CHECK(texture);
2319
2320 if (texture->getType() == Texture::TYPE_2D)
2321 return dynamic_cast<Texture2D*>(texture)->getLevel(attachment.level);
2322 else if (texture->getType() == Texture::TYPE_CUBE_MAP)
2323 return dynamic_cast<TextureCube*>(texture)->getFace(attachment.level, texTargetToFace(attachment.texTarget));
2324 else if (texture->getType() == Texture::TYPE_2D_ARRAY ||
2325 texture->getType() == Texture::TYPE_3D ||
2326 texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2327 {
2328 tcu::PixelBufferAccess level;
2329
2330 if (texture->getType() == Texture::TYPE_2D_ARRAY)
2331 level = dynamic_cast<Texture2DArray*>(texture)->getLevel(attachment.level);
2332 else if (texture->getType() == Texture::TYPE_3D)
2333 level = dynamic_cast<Texture3D*>(texture)->getLevel(attachment.level);
2334 else if (texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2335 level = dynamic_cast<TextureCubeArray*>(texture)->getLevel(attachment.level);
2336
2337 void* layerData = static_cast<deUint8*>(level.getDataPtr()) + level.getSlicePitch() * attachment.layer;
2338
2339 return tcu::PixelBufferAccess(level.getFormat(), level.getWidth(), level.getHeight(), 1, level.getRowPitch(), 0, layerData);
2340 }
2341 else
2342 return nullAccess();
2343 }
2344
2345 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
2346 {
2347 Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
2348 TCU_CHECK(rbo);
2349
2350 return rbo->getAccess();
2351 }
2352
2353 default:
2354 return nullAccess();
2355 }
2356 }
2357
getTexture2D(int unitNdx) const2358 const Texture2D& ReferenceContext::getTexture2D (int unitNdx) const
2359 {
2360 const TextureUnit& unit = m_textureUnits[unitNdx];
2361 return unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
2362 }
2363
getTextureCube(int unitNdx) const2364 const TextureCube& ReferenceContext::getTextureCube (int unitNdx) const
2365 {
2366 const TextureUnit& unit = m_textureUnits[unitNdx];
2367 return unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
2368 }
2369
isValidBufferTarget(deUint32 target)2370 static bool isValidBufferTarget (deUint32 target)
2371 {
2372 switch (target)
2373 {
2374 case GL_ARRAY_BUFFER:
2375 case GL_COPY_READ_BUFFER:
2376 case GL_COPY_WRITE_BUFFER:
2377 case GL_DRAW_INDIRECT_BUFFER:
2378 case GL_ELEMENT_ARRAY_BUFFER:
2379 case GL_PIXEL_PACK_BUFFER:
2380 case GL_PIXEL_UNPACK_BUFFER:
2381 case GL_TRANSFORM_FEEDBACK_BUFFER:
2382 case GL_UNIFORM_BUFFER:
2383 return true;
2384
2385 default:
2386 return false;
2387 }
2388 }
2389
setBufferBinding(deUint32 target,DataBuffer * buffer)2390 void ReferenceContext::setBufferBinding (deUint32 target, DataBuffer* buffer)
2391 {
2392 DataBuffer** bindingPoint = DE_NULL;
2393 VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2394
2395 switch (target)
2396 {
2397 case GL_ARRAY_BUFFER: bindingPoint = &m_arrayBufferBinding; break;
2398 case GL_COPY_READ_BUFFER: bindingPoint = &m_copyReadBufferBinding; break;
2399 case GL_COPY_WRITE_BUFFER: bindingPoint = &m_copyWriteBufferBinding; break;
2400 case GL_DRAW_INDIRECT_BUFFER: bindingPoint = &m_drawIndirectBufferBinding; break;
2401 case GL_ELEMENT_ARRAY_BUFFER: bindingPoint = &vertexArrayObject->m_elementArrayBufferBinding; break;
2402 case GL_PIXEL_PACK_BUFFER: bindingPoint = &m_pixelPackBufferBinding; break;
2403 case GL_PIXEL_UNPACK_BUFFER: bindingPoint = &m_pixelUnpackBufferBinding; break;
2404 case GL_TRANSFORM_FEEDBACK_BUFFER: bindingPoint = &m_transformFeedbackBufferBinding; break;
2405 case GL_UNIFORM_BUFFER: bindingPoint = &m_uniformBufferBinding; break;
2406 default:
2407 DE_ASSERT(false);
2408 return;
2409 }
2410
2411 if (*bindingPoint)
2412 {
2413 m_buffers.releaseReference(*bindingPoint);
2414 *bindingPoint = DE_NULL;
2415 }
2416
2417 if (buffer)
2418 m_buffers.acquireReference(buffer);
2419
2420 *bindingPoint = buffer;
2421 }
2422
getBufferBinding(deUint32 target) const2423 DataBuffer* ReferenceContext::getBufferBinding (deUint32 target) const
2424 {
2425 const VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2426
2427 switch (target)
2428 {
2429 case GL_ARRAY_BUFFER: return m_arrayBufferBinding;
2430 case GL_COPY_READ_BUFFER: return m_copyReadBufferBinding;
2431 case GL_COPY_WRITE_BUFFER: return m_copyWriteBufferBinding;
2432 case GL_DRAW_INDIRECT_BUFFER: return m_drawIndirectBufferBinding;
2433 case GL_ELEMENT_ARRAY_BUFFER: return vertexArrayObject->m_elementArrayBufferBinding;
2434 case GL_PIXEL_PACK_BUFFER: return m_pixelPackBufferBinding;
2435 case GL_PIXEL_UNPACK_BUFFER: return m_pixelUnpackBufferBinding;
2436 case GL_TRANSFORM_FEEDBACK_BUFFER: return m_transformFeedbackBufferBinding;
2437 case GL_UNIFORM_BUFFER: return m_uniformBufferBinding;
2438 default:
2439 DE_ASSERT(false);
2440 return DE_NULL;
2441 }
2442 }
2443
bindBuffer(deUint32 target,deUint32 buffer)2444 void ReferenceContext::bindBuffer (deUint32 target, deUint32 buffer)
2445 {
2446 RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2447
2448 rc::DataBuffer* bufObj = DE_NULL;
2449
2450 if (buffer != 0)
2451 {
2452 bufObj = m_buffers.find(buffer);
2453 if (!bufObj)
2454 {
2455 bufObj = new DataBuffer(buffer);
2456 m_buffers.insert(bufObj);
2457 }
2458 }
2459
2460 setBufferBinding(target, bufObj);
2461 }
2462
genBuffers(int numBuffers,deUint32 * buffers)2463 void ReferenceContext::genBuffers (int numBuffers, deUint32* buffers)
2464 {
2465 RC_IF_ERROR(!buffers, GL_INVALID_VALUE, RC_RET_VOID);
2466
2467 for (int ndx = 0; ndx < numBuffers; ndx++)
2468 buffers[ndx] = m_buffers.allocateName();
2469 }
2470
deleteBuffers(int numBuffers,const deUint32 * buffers)2471 void ReferenceContext::deleteBuffers (int numBuffers, const deUint32* buffers)
2472 {
2473 RC_IF_ERROR(numBuffers < 0, GL_INVALID_VALUE, RC_RET_VOID);
2474
2475 for (int ndx = 0; ndx < numBuffers; ndx++)
2476 {
2477 deUint32 buffer = buffers[ndx];
2478 DataBuffer* bufObj = DE_NULL;
2479
2480 if (buffer == 0)
2481 continue;
2482
2483 bufObj = m_buffers.find(buffer);
2484
2485 if (bufObj)
2486 deleteBuffer(bufObj);
2487 }
2488 }
2489
deleteBuffer(DataBuffer * buffer)2490 void ReferenceContext::deleteBuffer (DataBuffer* buffer)
2491 {
2492 static const deUint32 bindingPoints[] =
2493 {
2494 GL_ARRAY_BUFFER,
2495 GL_COPY_READ_BUFFER,
2496 GL_COPY_WRITE_BUFFER,
2497 GL_DRAW_INDIRECT_BUFFER,
2498 GL_ELEMENT_ARRAY_BUFFER,
2499 GL_PIXEL_PACK_BUFFER,
2500 GL_PIXEL_UNPACK_BUFFER,
2501 GL_TRANSFORM_FEEDBACK_BUFFER,
2502 GL_UNIFORM_BUFFER
2503 };
2504
2505 for (int bindingNdx = 0; bindingNdx < DE_LENGTH_OF_ARRAY(bindingPoints); bindingNdx++)
2506 {
2507 if (getBufferBinding(bindingPoints[bindingNdx]) == buffer)
2508 setBufferBinding(bindingPoints[bindingNdx], DE_NULL);
2509 }
2510
2511 {
2512 vector<VertexArray*> vertexArrays;
2513 m_vertexArrays.getAll(vertexArrays);
2514 vertexArrays.push_back(&m_clientVertexArray);
2515
2516 for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
2517 {
2518 if ((*i)->m_elementArrayBufferBinding == buffer)
2519 {
2520 m_buffers.releaseReference(buffer);
2521 (*i)->m_elementArrayBufferBinding = DE_NULL;
2522 }
2523
2524 for (size_t vertexAttribNdx = 0; vertexAttribNdx < (*i)->m_arrays.size(); ++vertexAttribNdx)
2525 {
2526 if ((*i)->m_arrays[vertexAttribNdx].bufferBinding == buffer)
2527 {
2528 m_buffers.releaseReference(buffer);
2529 (*i)->m_arrays[vertexAttribNdx].bufferDeleted = true;
2530 (*i)->m_arrays[vertexAttribNdx].bufferBinding = DE_NULL;
2531 }
2532 }
2533 }
2534 }
2535
2536 DE_ASSERT(buffer->getRefCount() == 1);
2537 m_buffers.releaseReference(buffer);
2538 }
2539
bufferData(deUint32 target,deIntptr size,const void * data,deUint32 usage)2540 void ReferenceContext::bufferData (deUint32 target, deIntptr size, const void* data, deUint32 usage)
2541 {
2542 RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2543 RC_IF_ERROR(size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2544
2545 DE_UNREF(usage);
2546
2547 DataBuffer* buffer = getBufferBinding(target);
2548 RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2549
2550 DE_ASSERT((deIntptr)(int)size == size);
2551 buffer->setStorage((int)size);
2552 if (data)
2553 deMemcpy(buffer->getData(), data, (int)size);
2554 }
2555
bufferSubData(deUint32 target,deIntptr offset,deIntptr size,const void * data)2556 void ReferenceContext::bufferSubData (deUint32 target, deIntptr offset, deIntptr size, const void* data)
2557 {
2558 RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2559 RC_IF_ERROR(offset < 0 || size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2560
2561 DataBuffer* buffer = getBufferBinding(target);
2562
2563 RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2564 RC_IF_ERROR((int)(offset+size) > buffer->getSize(), GL_INVALID_VALUE, RC_RET_VOID);
2565
2566 deMemcpy(buffer->getData()+offset, data, (int)size);
2567 }
2568
clearColor(float red,float green,float blue,float alpha)2569 void ReferenceContext::clearColor (float red, float green, float blue, float alpha)
2570 {
2571 m_clearColor = Vec4(de::clamp(red, 0.0f, 1.0f),
2572 de::clamp(green, 0.0f, 1.0f),
2573 de::clamp(blue, 0.0f, 1.0f),
2574 de::clamp(alpha, 0.0f, 1.0f));
2575 }
2576
clearDepthf(float depth)2577 void ReferenceContext::clearDepthf (float depth)
2578 {
2579 m_clearDepth = de::clamp(depth, 0.0f, 1.0f);
2580 }
2581
clearStencil(int stencil)2582 void ReferenceContext::clearStencil (int stencil)
2583 {
2584 m_clearStencil = stencil;
2585 }
2586
scissor(int x,int y,int width,int height)2587 void ReferenceContext::scissor (int x, int y, int width, int height)
2588 {
2589 RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
2590 m_scissorBox = IVec4(x, y, width, height);
2591 }
2592
enable(deUint32 cap)2593 void ReferenceContext::enable (deUint32 cap)
2594 {
2595 switch (cap)
2596 {
2597 case GL_BLEND: m_blendEnabled = true; break;
2598 case GL_SCISSOR_TEST: m_scissorEnabled = true; break;
2599 case GL_DEPTH_TEST: m_depthTestEnabled = true; break;
2600 case GL_STENCIL_TEST: m_stencilTestEnabled = true; break;
2601 case GL_POLYGON_OFFSET_FILL: m_polygonOffsetFillEnabled = true; break;
2602
2603 case GL_FRAMEBUFFER_SRGB:
2604 if (glu::isContextTypeGLCore(getType()))
2605 {
2606 m_sRGBUpdateEnabled = true;
2607 break;
2608 }
2609 setError(GL_INVALID_ENUM);
2610 break;
2611
2612 case GL_DEPTH_CLAMP:
2613 if (glu::isContextTypeGLCore(getType()))
2614 {
2615 m_depthClampEnabled = true;
2616 break;
2617 }
2618 setError(GL_INVALID_ENUM);
2619 break;
2620
2621 case GL_DITHER:
2622 // Not implemented - just ignored.
2623 break;
2624
2625 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2626 if (!glu::isContextTypeGLCore(getType()))
2627 {
2628 m_primitiveRestartFixedIndex = true;
2629 break;
2630 }
2631 setError(GL_INVALID_ENUM);
2632 break;
2633
2634 case GL_PRIMITIVE_RESTART:
2635 if (glu::isContextTypeGLCore(getType()))
2636 {
2637 m_primitiveRestartSettableIndex = true;
2638 break;
2639 }
2640 setError(GL_INVALID_ENUM);
2641 break;
2642
2643 default:
2644 setError(GL_INVALID_ENUM);
2645 break;
2646 }
2647 }
2648
disable(deUint32 cap)2649 void ReferenceContext::disable (deUint32 cap)
2650 {
2651 switch (cap)
2652 {
2653 case GL_BLEND: m_blendEnabled = false; break;
2654 case GL_SCISSOR_TEST: m_scissorEnabled = false; break;
2655 case GL_DEPTH_TEST: m_depthTestEnabled = false; break;
2656 case GL_STENCIL_TEST: m_stencilTestEnabled = false; break;
2657 case GL_POLYGON_OFFSET_FILL: m_polygonOffsetFillEnabled = false; break;
2658
2659 case GL_FRAMEBUFFER_SRGB:
2660 if (glu::isContextTypeGLCore(getType()))
2661 {
2662 m_sRGBUpdateEnabled = false;
2663 break;
2664 }
2665 setError(GL_INVALID_ENUM);
2666 break;
2667
2668 case GL_DEPTH_CLAMP:
2669 if (glu::isContextTypeGLCore(getType()))
2670 {
2671 m_depthClampEnabled = false;
2672 break;
2673 }
2674 setError(GL_INVALID_ENUM);
2675 break;
2676
2677 case GL_DITHER:
2678 break;
2679
2680 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2681 if (!glu::isContextTypeGLCore(getType()))
2682 {
2683 m_primitiveRestartFixedIndex = false;
2684 break;
2685 }
2686 setError(GL_INVALID_ENUM);
2687 break;
2688
2689 case GL_PRIMITIVE_RESTART:
2690 if (glu::isContextTypeGLCore(getType()))
2691 {
2692 m_primitiveRestartSettableIndex = false;
2693 break;
2694 }
2695 setError(GL_INVALID_ENUM);
2696 break;
2697
2698 default:
2699 setError(GL_INVALID_ENUM);
2700 break;
2701 }
2702 }
2703
isValidCompareFunc(deUint32 func)2704 static bool isValidCompareFunc (deUint32 func)
2705 {
2706 switch (func)
2707 {
2708 case GL_NEVER:
2709 case GL_LESS:
2710 case GL_LEQUAL:
2711 case GL_GREATER:
2712 case GL_GEQUAL:
2713 case GL_EQUAL:
2714 case GL_NOTEQUAL:
2715 case GL_ALWAYS:
2716 return true;
2717
2718 default:
2719 return false;
2720 }
2721 }
2722
isValidStencilOp(deUint32 op)2723 static bool isValidStencilOp (deUint32 op)
2724 {
2725 switch (op)
2726 {
2727 case GL_KEEP:
2728 case GL_ZERO:
2729 case GL_REPLACE:
2730 case GL_INCR:
2731 case GL_INCR_WRAP:
2732 case GL_DECR:
2733 case GL_DECR_WRAP:
2734 case GL_INVERT:
2735 return true;
2736
2737 default:
2738 return false;
2739 }
2740 }
2741
stencilFunc(deUint32 func,int ref,deUint32 mask)2742 void ReferenceContext::stencilFunc (deUint32 func, int ref, deUint32 mask)
2743 {
2744 stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
2745 }
2746
stencilFuncSeparate(deUint32 face,deUint32 func,int ref,deUint32 mask)2747 void ReferenceContext::stencilFuncSeparate (deUint32 face, deUint32 func, int ref, deUint32 mask)
2748 {
2749 const bool setFront = face == GL_FRONT || face == GL_FRONT_AND_BACK;
2750 const bool setBack = face == GL_BACK || face == GL_FRONT_AND_BACK;
2751
2752 RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2753 RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2754
2755 for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2756 {
2757 if ((type == rr::FACETYPE_FRONT && setFront) ||
2758 (type == rr::FACETYPE_BACK && setBack))
2759 {
2760 m_stencil[type].func = func;
2761 m_stencil[type].ref = ref;
2762 m_stencil[type].opMask = mask;
2763 }
2764 }
2765 }
2766
stencilOp(deUint32 sfail,deUint32 dpfail,deUint32 dppass)2767 void ReferenceContext::stencilOp (deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2768 {
2769 stencilOpSeparate(GL_FRONT_AND_BACK, sfail, dpfail, dppass);
2770 }
2771
stencilOpSeparate(deUint32 face,deUint32 sfail,deUint32 dpfail,deUint32 dppass)2772 void ReferenceContext::stencilOpSeparate (deUint32 face, deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2773 {
2774 const bool setFront = face == GL_FRONT || face == GL_FRONT_AND_BACK;
2775 const bool setBack = face == GL_BACK || face == GL_FRONT_AND_BACK;
2776
2777 RC_IF_ERROR(!isValidStencilOp(sfail) ||
2778 !isValidStencilOp(dpfail) ||
2779 !isValidStencilOp(dppass),
2780 GL_INVALID_ENUM, RC_RET_VOID);
2781 RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2782
2783 for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2784 {
2785 if ((type == rr::FACETYPE_FRONT && setFront) ||
2786 (type == rr::FACETYPE_BACK && setBack))
2787 {
2788 m_stencil[type].opStencilFail = sfail;
2789 m_stencil[type].opDepthFail = dpfail;
2790 m_stencil[type].opDepthPass = dppass;
2791 }
2792 }
2793 }
2794
depthFunc(deUint32 func)2795 void ReferenceContext::depthFunc (deUint32 func)
2796 {
2797 RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2798 m_depthFunc = func;
2799 }
2800
depthRangef(float n,float f)2801 void ReferenceContext::depthRangef (float n, float f)
2802 {
2803 m_depthRangeNear = de::clamp(n, 0.0f, 1.0f);
2804 m_depthRangeFar = de::clamp(f, 0.0f, 1.0f);
2805 }
2806
depthRange(double n,double f)2807 void ReferenceContext::depthRange (double n, double f)
2808 {
2809 depthRangef((float)n, (float)f);
2810 }
2811
polygonOffset(float factor,float units)2812 void ReferenceContext::polygonOffset (float factor, float units)
2813 {
2814 m_polygonOffsetFactor = factor;
2815 m_polygonOffsetUnits = units;
2816 }
2817
provokingVertex(deUint32 convention)2818 void ReferenceContext::provokingVertex (deUint32 convention)
2819 {
2820 // only in core
2821 DE_ASSERT(glu::isContextTypeGLCore(getType()));
2822
2823 switch (convention)
2824 {
2825 case GL_FIRST_VERTEX_CONVENTION: m_provokingFirstVertexConvention = true; break;
2826 case GL_LAST_VERTEX_CONVENTION: m_provokingFirstVertexConvention = false; break;
2827
2828 default:
2829 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
2830 }
2831 }
2832
primitiveRestartIndex(deUint32 index)2833 void ReferenceContext::primitiveRestartIndex (deUint32 index)
2834 {
2835 // only in core
2836 DE_ASSERT(glu::isContextTypeGLCore(getType()));
2837 m_primitiveRestartIndex = index;
2838 }
2839
isValidBlendEquation(deUint32 mode)2840 static inline bool isValidBlendEquation (deUint32 mode)
2841 {
2842 return mode == GL_FUNC_ADD ||
2843 mode == GL_FUNC_SUBTRACT ||
2844 mode == GL_FUNC_REVERSE_SUBTRACT ||
2845 mode == GL_MIN ||
2846 mode == GL_MAX;
2847 }
2848
isValidBlendFactor(deUint32 factor)2849 static bool isValidBlendFactor (deUint32 factor)
2850 {
2851 switch (factor)
2852 {
2853 case GL_ZERO:
2854 case GL_ONE:
2855 case GL_SRC_COLOR:
2856 case GL_ONE_MINUS_SRC_COLOR:
2857 case GL_DST_COLOR:
2858 case GL_ONE_MINUS_DST_COLOR:
2859 case GL_SRC_ALPHA:
2860 case GL_ONE_MINUS_SRC_ALPHA:
2861 case GL_DST_ALPHA:
2862 case GL_ONE_MINUS_DST_ALPHA:
2863 case GL_CONSTANT_COLOR:
2864 case GL_ONE_MINUS_CONSTANT_COLOR:
2865 case GL_CONSTANT_ALPHA:
2866 case GL_ONE_MINUS_CONSTANT_ALPHA:
2867 case GL_SRC_ALPHA_SATURATE:
2868 return true;
2869
2870 default:
2871 return false;
2872 }
2873 }
2874
blendEquation(deUint32 mode)2875 void ReferenceContext::blendEquation (deUint32 mode)
2876 {
2877 RC_IF_ERROR(!isValidBlendEquation(mode), GL_INVALID_ENUM, RC_RET_VOID);
2878
2879 m_blendModeRGB = mode;
2880 m_blendModeAlpha = mode;
2881 }
2882
blendEquationSeparate(deUint32 modeRGB,deUint32 modeAlpha)2883 void ReferenceContext::blendEquationSeparate (deUint32 modeRGB, deUint32 modeAlpha)
2884 {
2885 RC_IF_ERROR(!isValidBlendEquation(modeRGB) ||
2886 !isValidBlendEquation(modeAlpha),
2887 GL_INVALID_ENUM, RC_RET_VOID);
2888
2889 m_blendModeRGB = modeRGB;
2890 m_blendModeAlpha = modeAlpha;
2891 }
2892
blendFunc(deUint32 src,deUint32 dst)2893 void ReferenceContext::blendFunc (deUint32 src, deUint32 dst)
2894 {
2895 RC_IF_ERROR(!isValidBlendFactor(src) ||
2896 !isValidBlendFactor(dst),
2897 GL_INVALID_ENUM, RC_RET_VOID);
2898
2899 m_blendFactorSrcRGB = src;
2900 m_blendFactorSrcAlpha = src;
2901 m_blendFactorDstRGB = dst;
2902 m_blendFactorDstAlpha = dst;
2903 }
2904
blendFuncSeparate(deUint32 srcRGB,deUint32 dstRGB,deUint32 srcAlpha,deUint32 dstAlpha)2905 void ReferenceContext::blendFuncSeparate (deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
2906 {
2907 RC_IF_ERROR(!isValidBlendFactor(srcRGB) ||
2908 !isValidBlendFactor(dstRGB) ||
2909 !isValidBlendFactor(srcAlpha) ||
2910 !isValidBlendFactor(dstAlpha),
2911 GL_INVALID_ENUM, RC_RET_VOID);
2912
2913 m_blendFactorSrcRGB = srcRGB;
2914 m_blendFactorSrcAlpha = srcAlpha;
2915 m_blendFactorDstRGB = dstRGB;
2916 m_blendFactorDstAlpha = dstAlpha;
2917 }
2918
blendColor(float red,float green,float blue,float alpha)2919 void ReferenceContext::blendColor (float red, float green, float blue, float alpha)
2920 {
2921 m_blendColor = Vec4(de::clamp(red, 0.0f, 1.0f),
2922 de::clamp(green, 0.0f, 1.0f),
2923 de::clamp(blue, 0.0f, 1.0f),
2924 de::clamp(alpha, 0.0f, 1.0f));
2925 }
2926
colorMask(deBool r,deBool g,deBool b,deBool a)2927 void ReferenceContext::colorMask (deBool r, deBool g, deBool b, deBool a)
2928 {
2929 m_colorMask = tcu::BVec4(!!r, !!g, !!b, !!a);
2930 }
2931
depthMask(deBool mask)2932 void ReferenceContext::depthMask (deBool mask)
2933 {
2934 m_depthMask = !!mask;
2935 }
2936
stencilMask(deUint32 mask)2937 void ReferenceContext::stencilMask (deUint32 mask)
2938 {
2939 stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
2940 }
2941
stencilMaskSeparate(deUint32 face,deUint32 mask)2942 void ReferenceContext::stencilMaskSeparate (deUint32 face, deUint32 mask)
2943 {
2944 const bool setFront = face == GL_FRONT || face == GL_FRONT_AND_BACK;
2945 const bool setBack = face == GL_BACK || face == GL_FRONT_AND_BACK;
2946
2947 RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2948
2949 if (setFront) m_stencil[rr::FACETYPE_FRONT].writeMask = mask;
2950 if (setBack) m_stencil[rr::FACETYPE_BACK].writeMask = mask;
2951 }
2952
getNumStencilBits(const tcu::TextureFormat & format)2953 static int getNumStencilBits (const tcu::TextureFormat& format)
2954 {
2955 switch (format.order)
2956 {
2957 case tcu::TextureFormat::S:
2958 switch (format.type)
2959 {
2960 case tcu::TextureFormat::UNSIGNED_INT8: return 8;
2961 case tcu::TextureFormat::UNSIGNED_INT16: return 16;
2962 case tcu::TextureFormat::UNSIGNED_INT32: return 32;
2963 default:
2964 DE_ASSERT(false);
2965 return 0;
2966 }
2967
2968 case tcu::TextureFormat::DS:
2969 switch (format.type)
2970 {
2971 case tcu::TextureFormat::UNSIGNED_INT_24_8: return 8;
2972 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: return 8;
2973 default:
2974 DE_ASSERT(false);
2975 return 0;
2976 }
2977
2978 default:
2979 DE_ASSERT(false);
2980 return 0;
2981 }
2982 }
2983
maskStencil(int bits,int s)2984 static inline int maskStencil (int bits, int s) { return s & ((1<<bits)-1); }
2985
writeStencilOnly(const rr::MultisamplePixelBufferAccess & access,int s,int x,int y,int stencil,deUint32 writeMask)2986 static inline void writeStencilOnly (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, int stencil, deUint32 writeMask)
2987 {
2988 int const oldVal = access.raw().getPixelInt(s, x, y).w();
2989 access.raw().setPixStencil((oldVal & ~writeMask) | (stencil & writeMask), s, x, y);
2990 }
2991
writeDepthOnly(const rr::MultisamplePixelBufferAccess & access,int s,int x,int y,float depth)2992 static inline void writeDepthOnly (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, float depth)
2993 {
2994 access.raw().setPixDepth(depth, s, x, y);
2995 }
2996
blitResolveMultisampleFramebuffer(deUint32 mask,const IVec4 & srcRect,const IVec4 & dstRect,bool flipX,bool flipY)2997 deUint32 ReferenceContext::blitResolveMultisampleFramebuffer (deUint32 mask, const IVec4& srcRect, const IVec4& dstRect, bool flipX, bool flipY)
2998 {
2999 if (mask & GL_COLOR_BUFFER_BIT)
3000 {
3001 rr::MultisampleConstPixelBufferAccess src = rr::getSubregion(getReadColorbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3002 tcu::PixelBufferAccess dst = tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3003 tcu::TextureChannelClass dstClass = tcu::getTextureChannelClass(dst.getFormat().type);
3004 bool dstIsFloat = dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT ||
3005 dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
3006 dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3007 bool srcIsSRGB = src.raw().getFormat().order == tcu::TextureFormat::sRGB || src.raw().getFormat().order == tcu::TextureFormat::sRGBA;
3008 bool dstIsSRGB = dst.getFormat().order == tcu::TextureFormat::sRGB || dst.getFormat().order == tcu::TextureFormat::sRGBA;
3009 const bool convertSRGB = m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3010
3011 if (!convertSRGB)
3012 {
3013 tcu::ConstPixelBufferAccess srcRaw = src.raw();
3014 tcu::TextureFormat srcFmt = toNonSRGBFormat(srcRaw.getFormat());
3015
3016 srcRaw = tcu::ConstPixelBufferAccess(srcFmt, srcRaw.getWidth(), srcRaw.getHeight(), srcRaw.getDepth(), srcRaw.getRowPitch(), srcRaw.getSlicePitch(), srcRaw.getDataPtr());
3017 src = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(srcRaw);
3018
3019 dst = tcu::PixelBufferAccess(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3020 }
3021
3022 for (int x = 0; x < dstRect.z(); ++x)
3023 for (int y = 0; y < dstRect.w(); ++y)
3024 {
3025 int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3026 int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3027
3028 if (dstIsFloat || srcIsSRGB)
3029 {
3030 Vec4 p = src.raw().getPixel(0, srcX,srcY);
3031 dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, x, y);
3032 }
3033 else
3034 dst.setPixel(src.raw().getPixelInt(0, srcX, srcY), x, y);
3035 }
3036 }
3037
3038 if (mask & GL_DEPTH_BUFFER_BIT)
3039 {
3040 rr::MultisampleConstPixelBufferAccess src = rr::getSubregion(getReadColorbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3041 rr::MultisamplePixelBufferAccess dst = rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3042
3043 for (int x = 0; x < dstRect.z(); ++x)
3044 for (int y = 0; y < dstRect.w(); ++y)
3045 {
3046 int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3047 int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3048
3049 writeDepthOnly(dst, 0, x, y, src.raw().getPixel(0, srcX, srcY).x());
3050 }
3051 }
3052
3053 if (mask & GL_STENCIL_BUFFER_BIT)
3054 {
3055 rr::MultisampleConstPixelBufferAccess src = rr::getSubregion(getReadColorbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3056 rr::MultisamplePixelBufferAccess dst = rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3057
3058 for (int x = 0; x < dstRect.z(); ++x)
3059 for (int y = 0; y < dstRect.w(); ++y)
3060 {
3061 int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3062 int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3063
3064 writeStencilOnly(dst, 0, x, y, src.raw().getPixelInt(0, srcX, srcY).w(), m_stencil[rr::FACETYPE_FRONT].writeMask);
3065 }
3066 }
3067
3068 return GL_NO_ERROR;
3069 }
3070
blitFramebuffer(int srcX0,int srcY0,int srcX1,int srcY1,int dstX0,int dstY0,int dstX1,int dstY1,deUint32 mask,deUint32 filter)3071 void ReferenceContext::blitFramebuffer (int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, deUint32 mask, deUint32 filter)
3072 {
3073 // p0 in inclusive, p1 exclusive.
3074 // Negative width/height means swap.
3075 bool swapSrcX = srcX1 < srcX0;
3076 bool swapSrcY = srcY1 < srcY0;
3077 bool swapDstX = dstX1 < dstX0;
3078 bool swapDstY = dstY1 < dstY0;
3079 int srcW = de::abs(srcX1-srcX0);
3080 int srcH = de::abs(srcY1-srcY0);
3081 int dstW = de::abs(dstX1-dstX0);
3082 int dstH = de::abs(dstY1-dstY0);
3083 bool scale = srcW != dstW || srcH != dstH;
3084 int srcOriginX = swapSrcX ? srcX1 : srcX0;
3085 int srcOriginY = swapSrcY ? srcY1 : srcY0;
3086 int dstOriginX = swapDstX ? dstX1 : dstX0;
3087 int dstOriginY = swapDstY ? dstY1 : dstY0;
3088 IVec4 srcRect = IVec4(srcOriginX, srcOriginY, srcW, srcH);
3089 IVec4 dstRect = IVec4(dstOriginX, dstOriginY, dstW, dstH);
3090
3091 RC_IF_ERROR(filter != GL_NEAREST && filter != GL_LINEAR, GL_INVALID_ENUM, RC_RET_VOID);
3092 RC_IF_ERROR((mask & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0 && filter != GL_NEAREST, GL_INVALID_OPERATION, RC_RET_VOID);
3093
3094 // Validate that both targets are complete.
3095 RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ||
3096 checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_OPERATION, RC_RET_VOID);
3097
3098 // Check samples count is valid
3099 RC_IF_ERROR(getDrawColorbuffer().getNumSamples() != 1, GL_INVALID_OPERATION, RC_RET_VOID);
3100
3101 // Check size restrictions of multisampled case
3102 if (getReadColorbuffer().getNumSamples() != 1)
3103 {
3104 // Src and Dst rect dimensions must be the same
3105 RC_IF_ERROR(srcW != dstW || srcH != dstH, GL_INVALID_OPERATION, RC_RET_VOID);
3106
3107 // Framebuffer formats must match
3108 if (mask & GL_COLOR_BUFFER_BIT) RC_IF_ERROR(getReadColorbuffer().raw().getFormat() != getDrawColorbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3109 if (mask & GL_DEPTH_BUFFER_BIT) RC_IF_ERROR(getReadDepthbuffer().raw().getFormat() != getDrawDepthbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3110 if (mask & GL_STENCIL_BUFFER_BIT) RC_IF_ERROR(getReadStencilbuffer().raw().getFormat() != getDrawStencilbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3111 }
3112
3113 // Compute actual source rect.
3114 srcRect = (mask & GL_COLOR_BUFFER_BIT) ? intersect(srcRect, getBufferRect(getReadColorbuffer())) : srcRect;
3115 srcRect = (mask & GL_DEPTH_BUFFER_BIT) ? intersect(srcRect, getBufferRect(getReadDepthbuffer())) : srcRect;
3116 srcRect = (mask & GL_STENCIL_BUFFER_BIT) ? intersect(srcRect, getBufferRect(getReadStencilbuffer())) : srcRect;
3117
3118 // Compute destination rect.
3119 dstRect = (mask & GL_COLOR_BUFFER_BIT) ? intersect(dstRect, getBufferRect(getDrawColorbuffer())) : dstRect;
3120 dstRect = (mask & GL_DEPTH_BUFFER_BIT) ? intersect(dstRect, getBufferRect(getDrawDepthbuffer())) : dstRect;
3121 dstRect = (mask & GL_STENCIL_BUFFER_BIT) ? intersect(dstRect, getBufferRect(getDrawStencilbuffer())) : dstRect;
3122 dstRect = m_scissorEnabled ? intersect(dstRect, m_scissorBox) : dstRect;
3123
3124 if (isEmpty(srcRect) || isEmpty(dstRect))
3125 return; // Don't attempt copy.
3126
3127 // Multisampled read buffer is a special case
3128 if (getReadColorbuffer().getNumSamples() != 1)
3129 {
3130 deUint32 error = blitResolveMultisampleFramebuffer(mask, srcRect, dstRect, swapSrcX ^ swapDstX, swapSrcY ^ swapDstY);
3131
3132 if (error != GL_NO_ERROR)
3133 setError(error);
3134
3135 return;
3136 }
3137
3138 // \note Multisample pixel buffers can now be accessed like non-multisampled because multisample read buffer case is already handled. => sample count must be 1
3139
3140 // Coordinate transformation:
3141 // Dst offset space -> dst rectangle space -> src rectangle space -> src offset space.
3142 tcu::Mat3 transform = tcu::translationMatrix(Vec2((float)(srcX0 - srcRect.x()), (float)(srcY0 - srcRect.y())))
3143 * tcu::Mat3(Vec3((float)(srcX1-srcX0) / (float)(dstX1-dstX0),
3144 (float)(srcY1-srcY0) / (float)(dstY1-dstY0),
3145 1.0f))
3146 * tcu::translationMatrix(Vec2((float)(dstRect.x() - dstX0), (float)(dstRect.y() - dstY0)));
3147
3148 if (mask & GL_COLOR_BUFFER_BIT)
3149 {
3150 tcu::ConstPixelBufferAccess src = tcu::getSubregion(getReadColorbuffer().toSinglesampleAccess(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3151 tcu::PixelBufferAccess dst = tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3152 tcu::TextureChannelClass dstClass = tcu::getTextureChannelClass(dst.getFormat().type);
3153 bool dstIsFloat = dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT ||
3154 dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
3155 dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3156 tcu::Sampler::FilterMode sFilter = (scale && filter == GL_LINEAR) ? tcu::Sampler::LINEAR : tcu::Sampler::NEAREST;
3157 tcu::Sampler sampler (tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
3158 sFilter, sFilter, 0.0f /* lod threshold */, false /* non-normalized coords */);
3159 bool srcIsSRGB = src.getFormat().order == tcu::TextureFormat::sRGB || src.getFormat().order == tcu::TextureFormat::sRGBA;
3160 bool dstIsSRGB = dst.getFormat().order == tcu::TextureFormat::sRGB || dst.getFormat().order == tcu::TextureFormat::sRGBA;
3161 const bool convertSRGB = m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3162
3163 if (!convertSRGB)
3164 {
3165 src = tcu::ConstPixelBufferAccess (toNonSRGBFormat(src.getFormat()), src.getWidth(), src.getHeight(), src.getDepth(), src.getRowPitch(), src.getSlicePitch(), src.getDataPtr());
3166 dst = tcu::PixelBufferAccess (toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3167 }
3168
3169 // \note We don't check for unsupported conversions, unlike spec requires.
3170
3171 for (int yo = 0; yo < dstRect.w(); yo++)
3172 {
3173 for (int xo = 0; xo < dstRect.z(); xo++)
3174 {
3175 float dX = (float)xo + 0.5f;
3176 float dY = (float)yo + 0.5f;
3177
3178 // \note Only affine part is used.
3179 float sX = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3180 float sY = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3181
3182 // do not copy pixels outside the modified source region (modified by buffer intersection)
3183 if (sX < 0.0f || sX >= (float)srcRect.z() ||
3184 sY < 0.0f || sY >= (float)srcRect.w())
3185 continue;
3186
3187 if (dstIsFloat || srcIsSRGB || filter == tcu::Sampler::LINEAR)
3188 {
3189 Vec4 p = src.sample2D(sampler, sampler.minFilter, sX, sY, 0);
3190 dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, xo, yo);
3191 }
3192 else
3193 dst.setPixel(src.getPixelInt(deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)), xo, yo);
3194 }
3195 }
3196 }
3197
3198 if ((mask & GL_DEPTH_BUFFER_BIT) && m_depthMask)
3199 {
3200 rr::MultisampleConstPixelBufferAccess src = rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3201 rr::MultisamplePixelBufferAccess dst = rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3202
3203 for (int yo = 0; yo < dstRect.w(); yo++)
3204 {
3205 for (int xo = 0; xo < dstRect.z(); xo++)
3206 {
3207 const int sampleNdx = 0; // multisample read buffer case is already handled
3208
3209 float dX = (float)xo + 0.5f;
3210 float dY = (float)yo + 0.5f;
3211 float sX = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3212 float sY = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3213
3214 writeDepthOnly(dst, sampleNdx, xo, yo, src.raw().getPixel(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)).x());
3215 }
3216 }
3217 }
3218
3219 if (mask & GL_STENCIL_BUFFER_BIT)
3220 {
3221 rr::MultisampleConstPixelBufferAccess src = rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3222 rr::MultisamplePixelBufferAccess dst = rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3223
3224 for (int yo = 0; yo < dstRect.w(); yo++)
3225 {
3226 for (int xo = 0; xo < dstRect.z(); xo++)
3227 {
3228 const int sampleNdx = 0; // multisample read buffer case is already handled
3229
3230 float dX = (float)xo + 0.5f;
3231 float dY = (float)yo + 0.5f;
3232 float sX = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3233 float sY = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3234
3235 writeStencilOnly(dst, sampleNdx, xo, yo, src.raw().getPixelInt(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)).w(), m_stencil[rr::FACETYPE_FRONT].writeMask);
3236 }
3237 }
3238 }
3239 }
3240
invalidateSubFramebuffer(deUint32 target,int numAttachments,const deUint32 * attachments,int x,int y,int width,int height)3241 void ReferenceContext::invalidateSubFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments, int x, int y, int width, int height)
3242 {
3243 RC_IF_ERROR(target != GL_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
3244 RC_IF_ERROR((numAttachments < 0) || (numAttachments > 1 && attachments == DE_NULL), GL_INVALID_VALUE, RC_RET_VOID);
3245 RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
3246
3247 // \todo [2012-07-17 pyry] Support multiple color attachments.
3248
3249 const Vec4 colorClearValue (0.0f);
3250 const float depthClearValue = 1.0f;
3251 const int stencilClearValue = 0;
3252
3253 bool isFboBound = m_drawFramebufferBinding != DE_NULL;
3254 bool discardBuffers[3] = { false, false, false }; // Color, depth, stencil
3255
3256 for (int attNdx = 0; attNdx < numAttachments; attNdx++)
3257 {
3258 bool isColor = attachments[attNdx] == (isFboBound ? GL_COLOR_ATTACHMENT0 : GL_COLOR);
3259 bool isDepth = attachments[attNdx] == (isFboBound ? GL_DEPTH_ATTACHMENT : GL_DEPTH);
3260 bool isStencil = attachments[attNdx] == (isFboBound ? GL_STENCIL_ATTACHMENT : GL_STENCIL);
3261 bool isDepthStencil = isFboBound && attachments[attNdx] == GL_DEPTH_STENCIL_ATTACHMENT;
3262
3263 RC_IF_ERROR(!isColor && !isDepth && !isStencil && !isDepthStencil, GL_INVALID_VALUE, RC_RET_VOID);
3264
3265 if (isColor) discardBuffers[0] = true;
3266 if (isDepth || isDepthStencil) discardBuffers[1] = true;
3267 if (isStencil || isDepthStencil) discardBuffers[2] = true;
3268 }
3269
3270 for (int ndx = 0; ndx < 3; ndx++)
3271 {
3272 if (!discardBuffers[ndx])
3273 continue;
3274
3275 bool isColor = ndx == 0;
3276 bool isDepth = ndx == 1;
3277 bool isStencil = ndx == 2;
3278 rr::MultisamplePixelBufferAccess buf = isColor ? getDrawColorbuffer() :
3279 isDepth ? getDrawDepthbuffer() :
3280 getDrawStencilbuffer();
3281
3282 if (isEmpty(buf))
3283 continue;
3284
3285 tcu::IVec4 area = intersect(tcu::IVec4(0, 0, buf.raw().getHeight(), buf.raw().getDepth()), tcu::IVec4(x, y, width, height));
3286 rr::MultisamplePixelBufferAccess access = rr::getSubregion(buf, area.x(), area.y(), area.z(), area.w());
3287 bool isSharedDepthStencil = access.raw().getFormat().order == tcu::TextureFormat::DS;
3288
3289 if (isSharedDepthStencil)
3290 {
3291 for (int yo = 0; yo < access.raw().getDepth(); yo++)
3292 {
3293 for (int xo = 0; xo < access.raw().getHeight(); xo++)
3294 {
3295 for (int s = 0; s < access.getNumSamples(); s++)
3296 {
3297 if (isDepth)
3298 writeDepthOnly(access, s, xo, yo, depthClearValue);
3299 else if (isStencil)
3300 writeStencilOnly(access, s, xo, yo, stencilClearValue, 0xffffffffu);
3301 }
3302 }
3303 }
3304 }
3305 else
3306 {
3307 if (isColor)
3308 rr::clear(access, colorClearValue);
3309 else if (isDepth)
3310 rr::clear(access, tcu::Vec4(depthClearValue));
3311 else if (isStencil)
3312 rr::clear(access, tcu::IVec4(stencilClearValue));
3313 }
3314 }
3315 }
3316
invalidateFramebuffer(deUint32 target,int numAttachments,const deUint32 * attachments)3317 void ReferenceContext::invalidateFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments)
3318 {
3319 // \todo [2012-07-17 pyry] Support multiple color attachments.
3320 rr::MultisampleConstPixelBufferAccess colorBuf0 = getDrawColorbuffer();
3321 rr::MultisampleConstPixelBufferAccess depthBuf = getDrawDepthbuffer();
3322 rr::MultisampleConstPixelBufferAccess stencilBuf = getDrawStencilbuffer();
3323 int width = 0;
3324 int height = 0;
3325
3326 width = de::max(width, colorBuf0.raw().getHeight());
3327 width = de::max(width, depthBuf.raw().getHeight());
3328 width = de::max(width, stencilBuf.raw().getHeight());
3329
3330 height = de::max(height, colorBuf0.raw().getDepth());
3331 height = de::max(height, depthBuf.raw().getDepth());
3332 height = de::max(height, stencilBuf.raw().getDepth());
3333
3334 invalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, width, height);
3335 }
3336
clear(deUint32 buffers)3337 void ReferenceContext::clear (deUint32 buffers)
3338 {
3339 RC_IF_ERROR((buffers & ~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0, GL_INVALID_VALUE, RC_RET_VOID);
3340
3341 rr::MultisamplePixelBufferAccess colorBuf0 = getDrawColorbuffer();
3342 rr::MultisamplePixelBufferAccess depthBuf = getDrawDepthbuffer();
3343 rr::MultisamplePixelBufferAccess stencilBuf = getDrawStencilbuffer();
3344 bool hasColor0 = !isEmpty(colorBuf0);
3345 bool hasDepth = !isEmpty(depthBuf);
3346 bool hasStencil = !isEmpty(stencilBuf);
3347 IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3348
3349 if (hasColor0 && (buffers & GL_COLOR_BUFFER_BIT) != 0)
3350 {
3351 IVec4 colorArea = intersect(baseArea, getBufferRect(colorBuf0));
3352 rr::MultisamplePixelBufferAccess access = rr::getSubregion(colorBuf0, colorArea.x(), colorArea.y(), colorArea.z(), colorArea.w());
3353 bool isSRGB = colorBuf0.raw().getFormat().order == tcu::TextureFormat::sRGB || colorBuf0.raw().getFormat().order == tcu::TextureFormat::sRGBA;
3354 Vec4 c = (isSRGB && m_sRGBUpdateEnabled) ? tcu::linearToSRGB(m_clearColor) : m_clearColor;
3355 bool maskUsed = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3356 bool maskZero = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3357
3358 if (!maskUsed)
3359 rr::clear(access, c);
3360 else if (!maskZero)
3361 {
3362 for (int y = 0; y < access.raw().getDepth(); y++)
3363 for (int x = 0; x < access.raw().getHeight(); x++)
3364 for (int s = 0; s < access.getNumSamples(); s++)
3365 access.raw().setPixel(tcu::select(c, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3366 }
3367 // else all channels masked out
3368 }
3369
3370 if (hasDepth && (buffers & GL_DEPTH_BUFFER_BIT) != 0 && m_depthMask)
3371 {
3372 IVec4 depthArea = intersect(baseArea, getBufferRect(depthBuf));
3373 rr::MultisamplePixelBufferAccess access = rr::getSubregion(depthBuf, depthArea.x(), depthArea.y(), depthArea.z(), depthArea.w());
3374 bool isSharedDepthStencil = depthBuf.raw().getFormat().order != tcu::TextureFormat::D;
3375
3376 if (isSharedDepthStencil)
3377 {
3378 // Slow path where stencil is masked out in write.
3379 for (int y = 0; y < access.raw().getDepth(); y++)
3380 for (int x = 0; x < access.raw().getHeight(); x++)
3381 for (int s = 0; s < access.getNumSamples(); s++)
3382 writeDepthOnly(access, s, x, y, m_clearDepth);
3383 }
3384 else
3385 {
3386 // Fast path.
3387 int pixelSize = access.raw().getFormat().getPixelSize();
3388 std::vector<deUint8> row (access.raw().getWidth()*access.raw().getHeight()*pixelSize);
3389 tcu::PixelBufferAccess rowAccess (depthBuf.raw().getFormat(), access.raw().getWidth(), access.raw().getHeight(), 1, &row[0]);
3390
3391 for (int y = 0; y < rowAccess.getHeight(); y++)
3392 for (int x = 0; x < rowAccess.getWidth(); x++)
3393 rowAccess.setPixel(tcu::Vec4(m_clearDepth), x, y);
3394
3395 for (int y = 0; y < access.raw().getDepth(); y++)
3396 deMemcpy((deUint8*)access.raw().getDataPtr() + access.raw().getSlicePitch()*y, &row[0], (int)row.size());
3397 }
3398 }
3399
3400 if (hasStencil && (buffers & GL_STENCIL_BUFFER_BIT) != 0)
3401 {
3402 IVec4 stencilArea = intersect(baseArea, getBufferRect(stencilBuf));
3403 rr::MultisamplePixelBufferAccess access = rr::getSubregion(stencilBuf, stencilArea.x(), stencilArea.y(), stencilArea.z(), stencilArea.w());
3404 int stencilBits = getNumStencilBits(stencilBuf.raw().getFormat());
3405 int stencil = maskStencil(stencilBits, m_clearStencil);
3406 bool isSharedDepthStencil = stencilBuf.raw().getFormat().order != tcu::TextureFormat::S;
3407
3408 if (isSharedDepthStencil || ((m_stencil[rr::FACETYPE_FRONT].writeMask & ((1u<<stencilBits)-1u)) != ((1u<<stencilBits)-1u)))
3409 {
3410 // Slow path where depth or stencil is masked out in write.
3411 for (int y = 0; y < access.raw().getDepth(); y++)
3412 for (int x = 0; x < access.raw().getHeight(); x++)
3413 for (int s = 0; s < access.getNumSamples(); s++)
3414 writeStencilOnly(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3415 }
3416 else
3417 {
3418 // Fast path.
3419 int pixelSize = access.raw().getFormat().getPixelSize();
3420 std::vector<deUint8> row (access.raw().getWidth()*access.raw().getHeight()*pixelSize);
3421 tcu::PixelBufferAccess rowAccess (stencilBuf.raw().getFormat(), access.raw().getWidth(), access.raw().getHeight(), 1, &row[0]);
3422
3423 for (int y = 0; y < rowAccess.getHeight(); y++)
3424 for (int x = 0; x < rowAccess.getWidth(); x++)
3425 rowAccess.setPixel(tcu::IVec4(stencil), x, y);
3426
3427 for (int y = 0; y < access.raw().getDepth(); y++)
3428 deMemcpy((deUint8*)access.raw().getDataPtr() + access.raw().getSlicePitch()*y, &row[0], (int)row.size());
3429 }
3430 }
3431 }
3432
clearBufferiv(deUint32 buffer,int drawbuffer,const int * value)3433 void ReferenceContext::clearBufferiv (deUint32 buffer, int drawbuffer, const int* value)
3434 {
3435 RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3436 RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3437
3438 IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3439
3440 if (buffer == GL_COLOR)
3441 {
3442 rr::MultisamplePixelBufferAccess colorBuf = getDrawColorbuffer();
3443 bool maskUsed = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3444 bool maskZero = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3445
3446 if (!isEmpty(colorBuf) && !maskZero)
3447 {
3448 IVec4 area = intersect(baseArea, getBufferRect(colorBuf));
3449 rr::MultisamplePixelBufferAccess access = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3450 IVec4 color (value[0], value[1], value[2], value[3]);
3451
3452 if (!maskUsed)
3453 rr::clear(access, color);
3454 else
3455 {
3456 for (int y = 0; y < access.raw().getDepth(); y++)
3457 for (int x = 0; x < access.raw().getHeight(); x++)
3458 for (int s = 0; s < access.getNumSamples(); s++)
3459 access.raw().setPixel(tcu::select(color, access.raw().getPixelInt(s, x, y), m_colorMask), s, x, y);
3460 }
3461 }
3462 }
3463 else
3464 {
3465 TCU_CHECK_INTERNAL(buffer == GL_STENCIL);
3466
3467 rr::MultisamplePixelBufferAccess stencilBuf = getDrawStencilbuffer();
3468
3469 if (!isEmpty(stencilBuf) && m_stencil[rr::FACETYPE_FRONT].writeMask != 0)
3470 {
3471 IVec4 area = intersect(baseArea, getBufferRect(stencilBuf));
3472 rr::MultisamplePixelBufferAccess access = rr::getSubregion(stencilBuf, area.x(), area.y(), area.z(), area.w());
3473 int stencil = value[0];
3474
3475 for (int y = 0; y < access.raw().getDepth(); y++)
3476 for (int x = 0; x < access.raw().getHeight(); x++)
3477 for (int s = 0; s < access.getNumSamples(); s++)
3478 writeStencilOnly(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3479 }
3480 }
3481 }
3482
clearBufferfv(deUint32 buffer,int drawbuffer,const float * value)3483 void ReferenceContext::clearBufferfv (deUint32 buffer, int drawbuffer, const float* value)
3484 {
3485 RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_DEPTH, GL_INVALID_ENUM, RC_RET_VOID);
3486 RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3487
3488 IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3489
3490 if (buffer == GL_COLOR)
3491 {
3492 rr::MultisamplePixelBufferAccess colorBuf = getDrawColorbuffer();
3493 bool maskUsed = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3494 bool maskZero = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3495
3496 if (!isEmpty(colorBuf) && !maskZero)
3497 {
3498 IVec4 area = intersect(baseArea, getBufferRect(colorBuf));
3499 rr::MultisamplePixelBufferAccess access = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3500 Vec4 color (value[0], value[1], value[2], value[3]);
3501
3502 if (m_sRGBUpdateEnabled && (access.raw().getFormat().order == tcu::TextureFormat::sRGB ||
3503 access.raw().getFormat().order == tcu::TextureFormat::sRGBA))
3504 color = tcu::linearToSRGB(color);
3505
3506 if (!maskUsed)
3507 rr::clear(access, color);
3508 else
3509 {
3510 for (int y = 0; y < access.raw().getDepth(); y++)
3511 for (int x = 0; x < access.raw().getHeight(); x++)
3512 for (int s = 0; s < access.getNumSamples(); s++)
3513 access.raw().setPixel(tcu::select(color, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3514 }
3515 }
3516 }
3517 else
3518 {
3519 TCU_CHECK_INTERNAL(buffer == GL_DEPTH);
3520
3521 rr::MultisamplePixelBufferAccess depthBuf = getDrawDepthbuffer();
3522
3523 if (!isEmpty(depthBuf) && m_depthMask)
3524 {
3525 IVec4 area = intersect(baseArea, getBufferRect(depthBuf));
3526 rr::MultisamplePixelBufferAccess access = rr::getSubregion(depthBuf, area.x(), area.y(), area.z(), area.w());
3527 float depth = value[0];
3528
3529 for (int y = 0; y < access.raw().getDepth(); y++)
3530 for (int x = 0; x < access.raw().getHeight(); x++)
3531 for (int s = 0; s < access.getNumSamples(); s++)
3532 writeDepthOnly(access, s, x, y, depth);
3533 }
3534 }
3535 }
3536
clearBufferuiv(deUint32 buffer,int drawbuffer,const deUint32 * value)3537 void ReferenceContext::clearBufferuiv (deUint32 buffer, int drawbuffer, const deUint32* value)
3538 {
3539 RC_IF_ERROR(buffer != GL_COLOR, GL_INVALID_ENUM, RC_RET_VOID);
3540 RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3541
3542 IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3543
3544 TCU_CHECK_INTERNAL(buffer == GL_COLOR);
3545 {
3546 rr::MultisamplePixelBufferAccess colorBuf = getDrawColorbuffer();
3547 bool maskUsed = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3548 bool maskZero = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3549
3550 if (!isEmpty(colorBuf) && !maskZero)
3551 {
3552 IVec4 area = intersect(baseArea, getBufferRect(colorBuf));
3553 rr::MultisamplePixelBufferAccess access = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3554 tcu::UVec4 color (value[0], value[1], value[2], value[3]);
3555
3556 if (!maskUsed)
3557 rr::clear(access, color.asInt());
3558 else
3559 {
3560 for (int y = 0; y < access.raw().getDepth(); y++)
3561 for (int x = 0; x < access.raw().getHeight(); x++)
3562 for (int s = 0; s < access.getNumSamples(); s++)
3563 access.raw().setPixel(tcu::select(color, access.raw().getPixelUint(s, x, y), m_colorMask), s, x, y);
3564 }
3565 }
3566 }
3567 }
3568
clearBufferfi(deUint32 buffer,int drawbuffer,float depth,int stencil)3569 void ReferenceContext::clearBufferfi (deUint32 buffer, int drawbuffer, float depth, int stencil)
3570 {
3571 RC_IF_ERROR(buffer != GL_DEPTH_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3572 clearBufferfv(GL_DEPTH, drawbuffer, &depth);
3573 clearBufferiv(GL_STENCIL, drawbuffer, &stencil);
3574 }
3575
bindVertexArray(deUint32 array)3576 void ReferenceContext::bindVertexArray (deUint32 array)
3577 {
3578 rc::VertexArray* vertexArrayObject = DE_NULL;
3579
3580 if (array != 0)
3581 {
3582 vertexArrayObject = m_vertexArrays.find(array);
3583 if (!vertexArrayObject)
3584 {
3585 vertexArrayObject = new rc::VertexArray(array, m_limits.maxVertexAttribs);
3586 m_vertexArrays.insert(vertexArrayObject);
3587 }
3588 }
3589
3590 // Create new references
3591 if (vertexArrayObject)
3592 m_vertexArrays.acquireReference(vertexArrayObject);
3593
3594 // Remove old references
3595 if (m_vertexArrayBinding)
3596 m_vertexArrays.releaseReference(m_vertexArrayBinding);
3597
3598 m_vertexArrayBinding = vertexArrayObject;
3599 }
3600
genVertexArrays(int numArrays,deUint32 * vertexArrays)3601 void ReferenceContext::genVertexArrays (int numArrays, deUint32* vertexArrays)
3602 {
3603 RC_IF_ERROR(!vertexArrays, GL_INVALID_VALUE, RC_RET_VOID);
3604
3605 for (int ndx = 0; ndx < numArrays; ndx++)
3606 vertexArrays[ndx] = m_vertexArrays.allocateName();
3607 }
3608
deleteVertexArrays(int numArrays,const deUint32 * vertexArrays)3609 void ReferenceContext::deleteVertexArrays (int numArrays, const deUint32* vertexArrays)
3610 {
3611 for (int i = 0; i < numArrays; i++)
3612 {
3613 deUint32 name = vertexArrays[i];
3614 VertexArray* vertexArray = name ? m_vertexArrays.find(name) : DE_NULL;
3615
3616 if (vertexArray)
3617 deleteVertexArray(vertexArray);
3618 }
3619 }
3620
vertexAttribPointer(deUint32 index,int rawSize,deUint32 type,deBool normalized,int stride,const void * pointer)3621 void ReferenceContext::vertexAttribPointer (deUint32 index, int rawSize, deUint32 type, deBool normalized, int stride, const void *pointer)
3622 {
3623 const bool allowBGRA = !glu::isContextTypeES(getType());
3624 const int effectiveSize = (allowBGRA && rawSize == GL_BGRA) ? (4) : (rawSize);
3625
3626 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3627 RC_IF_ERROR(effectiveSize <= 0 || effectiveSize > 4, GL_INVALID_VALUE, RC_RET_VOID);
3628 RC_IF_ERROR(type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
3629 type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
3630 type != GL_INT && type != GL_UNSIGNED_INT &&
3631 type != GL_FIXED && type != GL_DOUBLE &&
3632 type != GL_FLOAT && type != GL_HALF_FLOAT &&
3633 type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_INT_2_10_10_10_REV, GL_INVALID_ENUM, RC_RET_VOID);
3634 RC_IF_ERROR(normalized != GL_TRUE && normalized != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3635 RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3636 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);
3637 RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3638 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);
3639 RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && normalized == GL_FALSE, GL_INVALID_OPERATION, RC_RET_VOID);
3640
3641 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3642
3643 vao.m_arrays[index].size = rawSize;
3644 vao.m_arrays[index].stride = stride;
3645 vao.m_arrays[index].type = type;
3646 vao.m_arrays[index].normalized = normalized == GL_TRUE;
3647 vao.m_arrays[index].integer = false;
3648 vao.m_arrays[index].pointer = pointer;
3649
3650 // acquire new reference
3651 if (m_arrayBufferBinding)
3652 m_buffers.acquireReference(m_arrayBufferBinding);
3653
3654 // release old reference
3655 if (vao.m_arrays[index].bufferBinding)
3656 m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3657
3658 vao.m_arrays[index].bufferDeleted = false;
3659 vao.m_arrays[index].bufferBinding = m_arrayBufferBinding;
3660 }
3661
vertexAttribIPointer(deUint32 index,int size,deUint32 type,int stride,const void * pointer)3662 void ReferenceContext::vertexAttribIPointer (deUint32 index, int size, deUint32 type, int stride, const void *pointer)
3663 {
3664 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3665 RC_IF_ERROR(size <= 0 || size > 4, GL_INVALID_VALUE, RC_RET_VOID);
3666 RC_IF_ERROR(type != GL_BYTE && type != GL_UNSIGNED_BYTE &&
3667 type != GL_SHORT && type != GL_UNSIGNED_SHORT &&
3668 type != GL_INT && type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
3669 RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3670 RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3671
3672 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3673
3674 vao.m_arrays[index].size = size;
3675 vao.m_arrays[index].stride = stride;
3676 vao.m_arrays[index].type = type;
3677 vao.m_arrays[index].normalized = false;
3678 vao.m_arrays[index].integer = true;
3679 vao.m_arrays[index].pointer = pointer;
3680
3681 // acquire new reference
3682 if (m_arrayBufferBinding)
3683 m_buffers.acquireReference(m_arrayBufferBinding);
3684
3685 // release old reference
3686 if (vao.m_arrays[index].bufferBinding)
3687 m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3688
3689 vao.m_arrays[index].bufferDeleted = false;
3690 vao.m_arrays[index].bufferBinding = m_arrayBufferBinding;
3691 }
3692
enableVertexAttribArray(deUint32 index)3693 void ReferenceContext::enableVertexAttribArray (deUint32 index)
3694 {
3695 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3696
3697 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3698 vao.m_arrays[index].enabled = true;
3699 }
3700
disableVertexAttribArray(deUint32 index)3701 void ReferenceContext::disableVertexAttribArray (deUint32 index)
3702 {
3703 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3704
3705 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3706 vao.m_arrays[index].enabled = false;
3707 }
3708
vertexAttribDivisor(deUint32 index,deUint32 divisor)3709 void ReferenceContext::vertexAttribDivisor (deUint32 index, deUint32 divisor)
3710 {
3711 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3712
3713 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3714 vao.m_arrays[index].divisor = divisor;
3715 }
3716
vertexAttrib1f(deUint32 index,float x)3717 void ReferenceContext::vertexAttrib1f (deUint32 index, float x)
3718 {
3719 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3720
3721 m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, 0, 0, 1));
3722 }
3723
vertexAttrib2f(deUint32 index,float x,float y)3724 void ReferenceContext::vertexAttrib2f (deUint32 index, float x, float y)
3725 {
3726 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3727
3728 m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, 0, 1));
3729 }
3730
vertexAttrib3f(deUint32 index,float x,float y,float z)3731 void ReferenceContext::vertexAttrib3f (deUint32 index, float x, float y, float z)
3732 {
3733 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3734
3735 m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, 1));
3736 }
3737
vertexAttrib4f(deUint32 index,float x,float y,float z,float w)3738 void ReferenceContext::vertexAttrib4f (deUint32 index, float x, float y, float z, float w)
3739 {
3740 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3741
3742 m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, w));
3743 }
3744
vertexAttribI4i(deUint32 index,deInt32 x,deInt32 y,deInt32 z,deInt32 w)3745 void ReferenceContext::vertexAttribI4i (deUint32 index, deInt32 x, deInt32 y, deInt32 z, deInt32 w)
3746 {
3747 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3748
3749 m_currentAttribs[index] = rr::GenericVec4(tcu::IVec4(x, y, z, w));
3750 }
3751
vertexAttribI4ui(deUint32 index,deUint32 x,deUint32 y,deUint32 z,deUint32 w)3752 void ReferenceContext::vertexAttribI4ui (deUint32 index, deUint32 x, deUint32 y, deUint32 z, deUint32 w)
3753 {
3754 RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3755
3756 m_currentAttribs[index] = rr::GenericVec4(tcu::UVec4(x, y, z, w));
3757 }
3758
getAttribLocation(deUint32 program,const char * name)3759 deInt32 ReferenceContext::getAttribLocation (deUint32 program, const char *name)
3760 {
3761 ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3762
3763 RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3764
3765 if (name)
3766 {
3767 std::string nameString(name);
3768
3769 for (size_t ndx = 0; ndx < shaderProg->m_program->m_attributeNames.size(); ++ndx)
3770 if (shaderProg->m_program->m_attributeNames[ndx] == nameString)
3771 return (int)ndx;
3772 }
3773
3774 return -1;
3775 }
3776
uniformv(deInt32 location,glu::DataType type,deInt32 count,const void * v)3777 void ReferenceContext::uniformv (deInt32 location, glu::DataType type, deInt32 count, const void* v)
3778 {
3779 RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3780
3781 std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3782
3783 if (location == -1)
3784 return;
3785
3786 RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3787 RC_IF_ERROR(uniforms[location].type != type, GL_INVALID_OPERATION, RC_RET_VOID);
3788 RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3789
3790 {
3791 const int scalarSize = glu::getDataTypeScalarSize(type);
3792 DE_ASSERT(scalarSize*sizeof(deUint32) <= sizeof(uniforms[location].value));
3793 deMemcpy(&uniforms[location].value, v, scalarSize*(int)sizeof(deUint32));
3794 }
3795 }
3796
uniform1iv(deInt32 location,deInt32 count,const deInt32 * v)3797 void ReferenceContext::uniform1iv (deInt32 location, deInt32 count, const deInt32* v)
3798 {
3799 RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3800
3801 std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3802
3803 if (location == -1)
3804 return;
3805
3806 RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3807 RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3808
3809 switch (uniforms[location].type)
3810 {
3811 case glu::TYPE_INT: uniforms[location].value.i = *v; return;
3812
3813 // \note texture unit is stored to value
3814 case glu::TYPE_SAMPLER_2D:
3815 case glu::TYPE_UINT_SAMPLER_2D:
3816 case glu::TYPE_INT_SAMPLER_2D:
3817 case glu::TYPE_SAMPLER_CUBE:
3818 case glu::TYPE_UINT_SAMPLER_CUBE:
3819 case glu::TYPE_INT_SAMPLER_CUBE:
3820 case glu::TYPE_SAMPLER_2D_ARRAY:
3821 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
3822 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
3823 case glu::TYPE_SAMPLER_3D:
3824 case glu::TYPE_UINT_SAMPLER_3D:
3825 case glu::TYPE_INT_SAMPLER_3D:
3826 case glu::TYPE_SAMPLER_CUBE_ARRAY:
3827 case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
3828 case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
3829 uniforms[location].value.i = *v;
3830 return;
3831
3832 default:
3833 setError(GL_INVALID_OPERATION);
3834 return;
3835 }
3836 }
3837
uniform1f(deInt32 location,const float v0)3838 void ReferenceContext::uniform1f (deInt32 location, const float v0)
3839 {
3840 uniform1fv(location, 1, &v0);
3841 }
3842
uniform1i(deInt32 location,deInt32 v0)3843 void ReferenceContext::uniform1i (deInt32 location, deInt32 v0)
3844 {
3845 uniform1iv(location, 1, &v0);
3846 }
3847
uniform1fv(deInt32 location,deInt32 count,const float * v)3848 void ReferenceContext::uniform1fv (deInt32 location, deInt32 count, const float* v)
3849 {
3850 uniformv(location, glu::TYPE_FLOAT, count, v);
3851 }
3852
uniform2fv(deInt32 location,deInt32 count,const float * v)3853 void ReferenceContext::uniform2fv (deInt32 location, deInt32 count, const float* v)
3854 {
3855 uniformv(location, glu::TYPE_FLOAT_VEC2, count, v);
3856 }
3857
uniform3fv(deInt32 location,deInt32 count,const float * v)3858 void ReferenceContext::uniform3fv (deInt32 location, deInt32 count, const float* v)
3859 {
3860 uniformv(location, glu::TYPE_FLOAT_VEC3, count, v);
3861 }
3862
uniform4fv(deInt32 location,deInt32 count,const float * v)3863 void ReferenceContext::uniform4fv (deInt32 location, deInt32 count, const float* v)
3864 {
3865 uniformv(location, glu::TYPE_FLOAT_VEC4, count, v);
3866 }
3867
uniform2iv(deInt32 location,deInt32 count,const deInt32 * v)3868 void ReferenceContext::uniform2iv (deInt32 location, deInt32 count, const deInt32* v)
3869 {
3870 uniformv(location, glu::TYPE_INT_VEC2, count, v);
3871 }
3872
uniform3iv(deInt32 location,deInt32 count,const deInt32 * v)3873 void ReferenceContext::uniform3iv (deInt32 location, deInt32 count, const deInt32* v)
3874 {
3875 uniformv(location, glu::TYPE_INT_VEC3, count, v);
3876 }
3877
uniform4iv(deInt32 location,deInt32 count,const deInt32 * v)3878 void ReferenceContext::uniform4iv (deInt32 location, deInt32 count, const deInt32* v)
3879 {
3880 uniformv(location, glu::TYPE_INT_VEC4, count, v);
3881 }
3882
uniformMatrix3fv(deInt32 location,deInt32 count,deInt32 transpose,const float * value)3883 void ReferenceContext::uniformMatrix3fv (deInt32 location, deInt32 count, deInt32 transpose, const float *value)
3884 {
3885 RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3886
3887 std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3888
3889 if (location == -1)
3890 return;
3891
3892 RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3893
3894 if (count == 0)
3895 return;
3896
3897 RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3898
3899 switch (uniforms[location].type)
3900 {
3901 case glu::TYPE_FLOAT_MAT3:
3902 RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3903
3904 if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3905 for (int row = 0; row < 3; ++row)
3906 for (int col = 0; col < 3; ++col)
3907 uniforms[location].value.m3[row*3+col] = value[col*3+row];
3908 else // input is row major
3909 for (int row = 0; row < 3; ++row)
3910 for (int col = 0; col < 3; ++col)
3911 uniforms[location].value.m3[row*3+col] = value[row*3+col];
3912
3913 break;
3914
3915 default:
3916 setError(GL_INVALID_OPERATION);
3917 return;
3918 }
3919 }
3920
uniformMatrix4fv(deInt32 location,deInt32 count,deInt32 transpose,const float * value)3921 void ReferenceContext::uniformMatrix4fv (deInt32 location, deInt32 count, deInt32 transpose, const float *value)
3922 {
3923 RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3924
3925 std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3926
3927 if (location == -1)
3928 return;
3929
3930 RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3931
3932 if (count == 0)
3933 return;
3934
3935 RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3936
3937 switch (uniforms[location].type)
3938 {
3939 case glu::TYPE_FLOAT_MAT4:
3940 RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3941
3942 if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3943 for (int row = 0; row < 4; ++row)
3944 for (int col = 0; col < 4; ++col)
3945 uniforms[location].value.m4[row*3+col] = value[col*3+row];
3946 else // input is row major
3947 for (int row = 0; row < 4; ++row)
3948 for (int col = 0; col < 4; ++col)
3949 uniforms[location].value.m4[row*3+col] = value[row*3+col];
3950
3951 break;
3952
3953 default:
3954 setError(GL_INVALID_OPERATION);
3955 return;
3956 }
3957 }
3958
getUniformLocation(deUint32 program,const char * name)3959 deInt32 ReferenceContext::getUniformLocation (deUint32 program, const char *name)
3960 {
3961 ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3962 RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3963
3964 std::vector<sglr::UniformSlot>& uniforms = shaderProg->m_program->m_uniforms;
3965
3966 for (size_t i = 0; i < uniforms.size(); ++i)
3967 if (name && deStringEqual(uniforms[i].name.c_str(), name))
3968 return (int)i;
3969
3970 return -1;
3971 }
3972
lineWidth(float w)3973 void ReferenceContext::lineWidth (float w)
3974 {
3975 RC_IF_ERROR(w < 0.0f, GL_INVALID_VALUE, RC_RET_VOID);
3976 m_lineWidth = w;
3977 }
3978
deleteVertexArray(rc::VertexArray * vertexArray)3979 void ReferenceContext::deleteVertexArray (rc::VertexArray* vertexArray)
3980 {
3981 if (m_vertexArrayBinding == vertexArray)
3982 bindVertexArray(0);
3983
3984 if (vertexArray->m_elementArrayBufferBinding)
3985 m_buffers.releaseReference(vertexArray->m_elementArrayBufferBinding);
3986
3987 for (size_t ndx = 0; ndx < vertexArray->m_arrays.size(); ++ndx)
3988 if (vertexArray->m_arrays[ndx].bufferBinding)
3989 m_buffers.releaseReference(vertexArray->m_arrays[ndx].bufferBinding);
3990
3991 DE_ASSERT(vertexArray->getRefCount() == 1);
3992 m_vertexArrays.releaseReference(vertexArray);
3993 }
3994
deleteProgramObject(rc::ShaderProgramObjectContainer * sp)3995 void ReferenceContext::deleteProgramObject (rc::ShaderProgramObjectContainer* sp)
3996 {
3997 // Unbinding program will delete it
3998 if (m_currentProgram == sp && sp->m_deleteFlag)
3999 {
4000 useProgram(0);
4001 return;
4002 }
4003
4004 // Unbinding program will NOT delete it
4005 if (m_currentProgram == sp)
4006 useProgram(0);
4007
4008 DE_ASSERT(sp->getRefCount() == 1);
4009 m_programs.releaseReference(sp);
4010 }
4011
drawArrays(deUint32 mode,int first,int count)4012 void ReferenceContext::drawArrays (deUint32 mode, int first, int count)
4013 {
4014 drawArraysInstanced(mode, first, count, 1);
4015 }
4016
drawArraysInstanced(deUint32 mode,int first,int count,int instanceCount)4017 void ReferenceContext::drawArraysInstanced (deUint32 mode, int first, int count, int instanceCount)
4018 {
4019 // Error conditions
4020 {
4021 RC_IF_ERROR(first < 0 || count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4022
4023 if (!predrawErrorChecks(mode))
4024 return;
4025 }
4026
4027 // All is ok
4028 {
4029 const rr::PrimitiveType primitiveType = sglr::rr_util::mapGLPrimitiveType(mode);
4030
4031 drawWithReference(rr::PrimitiveList(primitiveType, count, first), instanceCount);
4032 }
4033 }
4034
drawElements(deUint32 mode,int count,deUint32 type,const void * indices)4035 void ReferenceContext::drawElements (deUint32 mode, int count, deUint32 type, const void *indices)
4036 {
4037 drawElementsInstanced(mode, count, type, indices, 1);
4038 }
4039
drawElementsBaseVertex(deUint32 mode,int count,deUint32 type,const void * indices,int baseVertex)4040 void ReferenceContext::drawElementsBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int baseVertex)
4041 {
4042 drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex);
4043 }
4044
drawElementsInstanced(deUint32 mode,int count,deUint32 type,const void * indices,int instanceCount)4045 void ReferenceContext::drawElementsInstanced (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount)
4046 {
4047 drawElementsInstancedBaseVertex(mode, count, type, indices, instanceCount, 0);
4048 }
4049
drawElementsInstancedBaseVertex(deUint32 mode,int count,deUint32 type,const void * indices,int instanceCount,int baseVertex)4050 void ReferenceContext::drawElementsInstancedBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount, int baseVertex)
4051 {
4052 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4053
4054 // Error conditions
4055 {
4056 RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4057 type != GL_UNSIGNED_SHORT &&
4058 type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4059 RC_IF_ERROR(count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4060
4061 if (!predrawErrorChecks(mode))
4062 return;
4063 }
4064
4065 // All is ok
4066 {
4067 const rr::PrimitiveType primitiveType = sglr::rr_util::mapGLPrimitiveType(mode);
4068 const void* indicesPtr = (vao.m_elementArrayBufferBinding) ? (vao.m_elementArrayBufferBinding->getData() + ((const deUint8*)indices - (const deUint8*)DE_NULL)) : (indices);
4069
4070 drawWithReference(rr::PrimitiveList(primitiveType, count, rr::DrawIndices(indicesPtr, sglr::rr_util::mapGLIndexType(type), baseVertex)), instanceCount);
4071 }
4072 }
4073
drawRangeElements(deUint32 mode,deUint32 start,deUint32 end,int count,deUint32 type,const void * indices)4074 void ReferenceContext::drawRangeElements (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices)
4075 {
4076 RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4077
4078 drawElements(mode, count, type, indices);
4079 }
4080
drawRangeElementsBaseVertex(deUint32 mode,deUint32 start,deUint32 end,int count,deUint32 type,const void * indices,int baseVertex)4081 void ReferenceContext::drawRangeElementsBaseVertex (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices, int baseVertex)
4082 {
4083 RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4084
4085 drawElementsBaseVertex(mode, count, type, indices, baseVertex);
4086 }
4087
drawArraysIndirect(deUint32 mode,const void * indirect)4088 void ReferenceContext::drawArraysIndirect (deUint32 mode, const void *indirect)
4089 {
4090 struct DrawArraysIndirectCommand
4091 {
4092 deUint32 count;
4093 deUint32 primCount;
4094 deUint32 first;
4095 deUint32 reservedMustBeZero;
4096 };
4097
4098 const DrawArraysIndirectCommand* command;
4099
4100 // Check errors
4101
4102 if (!predrawErrorChecks(mode))
4103 return;
4104
4105 // Check pointer validity
4106
4107 RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4108 RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4109
4110 // \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4111 RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4112 RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL) + sizeof(DrawArraysIndirectCommand) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4113
4114 // Check values
4115
4116 command = (const DrawArraysIndirectCommand*)(m_drawIndirectBufferBinding->getData() + ((const char*)indirect - (const char*)DE_NULL));
4117 RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4118
4119 // draw
4120 drawArraysInstanced(mode, command->first, command->count, command->primCount);
4121 }
4122
drawElementsIndirect(deUint32 mode,deUint32 type,const void * indirect)4123 void ReferenceContext::drawElementsIndirect (deUint32 mode, deUint32 type, const void *indirect)
4124 {
4125 struct DrawElementsIndirectCommand
4126 {
4127 deUint32 count;
4128 deUint32 primCount;
4129 deUint32 firstIndex;
4130 deInt32 baseVertex;
4131 deUint32 reservedMustBeZero;
4132 };
4133
4134 const DrawElementsIndirectCommand* command;
4135
4136 // Check errors
4137
4138 if (!predrawErrorChecks(mode))
4139 return;
4140
4141 RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4142 type != GL_UNSIGNED_SHORT &&
4143 type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4144
4145 RC_IF_ERROR(!getBufferBinding(GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_OPERATION, RC_RET_VOID);
4146
4147 // Check pointer validity
4148
4149 RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4150 RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4151
4152 // \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4153 RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4154 RC_IF_ERROR((size_t)((const char*)indirect - (const char*)DE_NULL) + sizeof(DrawElementsIndirectCommand) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4155
4156 // Check values
4157
4158 command = (const DrawElementsIndirectCommand*)(m_drawIndirectBufferBinding->getData() + ((const char*)indirect - (const char*)DE_NULL));
4159 RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4160
4161 // Check command error conditions
4162 RC_IF_ERROR((int)command->count < 0 || (int)command->primCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4163
4164 // Draw
4165 {
4166 const size_t sizeOfType = (type == GL_UNSIGNED_BYTE) ? (1) : ((type == GL_UNSIGNED_SHORT) ? (2) : (4));
4167 const void* indicesPtr = (deUint8*)DE_NULL + (command->firstIndex * sizeOfType);
4168
4169 drawElementsInstancedBaseVertex(mode, (int)command->count, type, indicesPtr, (int)command->primCount, command->baseVertex);
4170 }
4171 }
4172
multiDrawArrays(deUint32 mode,const int * first,const int * count,int primCount)4173 void ReferenceContext::multiDrawArrays (deUint32 mode, const int* first, const int* count, int primCount)
4174 {
4175 DE_UNREF(mode);
4176 DE_UNREF(first);
4177 DE_UNREF(count);
4178 DE_UNREF(primCount);
4179
4180 // not supported in gles, prevent accidental use
4181 DE_ASSERT(false);
4182 }
4183
multiDrawElements(deUint32 mode,const int * count,deUint32 type,const void ** indices,int primCount)4184 void ReferenceContext::multiDrawElements (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount)
4185 {
4186 DE_UNREF(mode);
4187 DE_UNREF(count);
4188 DE_UNREF(type);
4189 DE_UNREF(indices);
4190 DE_UNREF(primCount);
4191
4192 // not supported in gles, prevent accidental use
4193 DE_ASSERT(false);
4194 }
4195
multiDrawElementsBaseVertex(deUint32 mode,const int * count,deUint32 type,const void ** indices,int primCount,const int * baseVertex)4196 void ReferenceContext::multiDrawElementsBaseVertex (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount, const int* baseVertex)
4197 {
4198 DE_UNREF(mode);
4199 DE_UNREF(count);
4200 DE_UNREF(type);
4201 DE_UNREF(indices);
4202 DE_UNREF(primCount);
4203 DE_UNREF(baseVertex);
4204
4205 // not supported in gles, prevent accidental use
4206 DE_ASSERT(false);
4207 }
4208
predrawErrorChecks(deUint32 mode)4209 bool ReferenceContext::predrawErrorChecks (deUint32 mode)
4210 {
4211 RC_IF_ERROR(mode != GL_POINTS &&
4212 mode != GL_LINE_STRIP && mode != GL_LINE_LOOP && mode != GL_LINES &&
4213 mode != GL_TRIANGLE_STRIP && mode != GL_TRIANGLE_FAN && mode != GL_TRIANGLES &&
4214 mode != GL_LINES_ADJACENCY && mode != GL_LINE_STRIP_ADJACENCY &&
4215 mode != GL_TRIANGLES_ADJACENCY && mode != GL_TRIANGLE_STRIP_ADJACENCY,
4216 GL_INVALID_ENUM, false);
4217
4218 // \todo [jarkko] Uncomment following code when the buffer mapping support is added
4219 //for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4220 // if (vao.m_arrays[ndx].enabled && vao.m_arrays[ndx].bufferBinding && vao.m_arrays[ndx].bufferBinding->isMapped)
4221 // RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4222
4223 RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION, false);
4224
4225 // Geometry shader checks
4226 if (m_currentProgram && m_currentProgram->m_program->m_hasGeometryShader)
4227 {
4228 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS && mode != GL_POINTS, GL_INVALID_OPERATION, false);
4229
4230 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
4231 (mode != GL_LINES &&
4232 mode != GL_LINE_STRIP &&
4233 mode != GL_LINE_LOOP),
4234 GL_INVALID_OPERATION, false);
4235
4236 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
4237 (mode != GL_TRIANGLES &&
4238 mode != GL_TRIANGLE_STRIP &&
4239 mode != GL_TRIANGLE_FAN),
4240 GL_INVALID_OPERATION, false);
4241
4242 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
4243 (mode != GL_LINES_ADJACENCY &&
4244 mode != GL_LINE_STRIP_ADJACENCY),
4245 GL_INVALID_OPERATION, false);
4246
4247 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
4248 (mode != GL_TRIANGLES_ADJACENCY &&
4249 mode != GL_TRIANGLE_STRIP_ADJACENCY),
4250 GL_INVALID_OPERATION, false);
4251 }
4252
4253 return true;
4254 }
4255
getPrimitiveBaseType(rr::PrimitiveType derivedType)4256 static rr::PrimitiveType getPrimitiveBaseType (rr::PrimitiveType derivedType)
4257 {
4258 switch (derivedType)
4259 {
4260 case rr::PRIMITIVETYPE_TRIANGLES:
4261 case rr::PRIMITIVETYPE_TRIANGLE_STRIP:
4262 case rr::PRIMITIVETYPE_TRIANGLE_FAN:
4263 case rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY:
4264 case rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:
4265 return rr::PRIMITIVETYPE_TRIANGLES;
4266
4267 case rr::PRIMITIVETYPE_LINES:
4268 case rr::PRIMITIVETYPE_LINE_STRIP:
4269 case rr::PRIMITIVETYPE_LINE_LOOP:
4270 case rr::PRIMITIVETYPE_LINES_ADJACENCY:
4271 case rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY:
4272 return rr::PRIMITIVETYPE_LINES;
4273
4274 case rr::PRIMITIVETYPE_POINTS:
4275 return rr::PRIMITIVETYPE_POINTS;
4276
4277 default:
4278 DE_ASSERT(false);
4279 return rr::PRIMITIVETYPE_LAST;
4280 }
4281 }
4282
getFixedRestartIndex(rr::IndexType indexType)4283 static deUint32 getFixedRestartIndex (rr::IndexType indexType)
4284 {
4285 switch (indexType)
4286 {
4287 case rr::INDEXTYPE_UINT8: return 0xFF;
4288 case rr::INDEXTYPE_UINT16: return 0xFFFF;
4289 case rr::INDEXTYPE_UINT32: return 0xFFFFFFFFul;
4290
4291 case rr::INDEXTYPE_LAST:
4292 default:
4293 DE_ASSERT(false);
4294 return 0;
4295 }
4296 }
4297
drawWithReference(const rr::PrimitiveList & primitives,int instanceCount)4298 void ReferenceContext::drawWithReference (const rr::PrimitiveList& primitives, int instanceCount)
4299 {
4300 // undefined results
4301 if (m_currentProgram == DE_NULL)
4302 return;
4303
4304 rr::MultisamplePixelBufferAccess colorBuf0 = getDrawColorbuffer();
4305 rr::MultisamplePixelBufferAccess depthBuf = getDrawDepthbuffer();
4306 rr::MultisamplePixelBufferAccess stencilBuf = getDrawStencilbuffer();
4307 const bool hasStencil = !isEmpty(stencilBuf);
4308 const int stencilBits = (hasStencil) ? (getNumStencilBits(stencilBuf.raw().getFormat())) : (0);
4309
4310 const rr::RenderTarget renderTarget(colorBuf0, depthBuf,stencilBuf);
4311 const rr::Program program (m_currentProgram->m_program->getVertexShader(),
4312 m_currentProgram->m_program->getFragmentShader(),
4313 (m_currentProgram->m_program->m_hasGeometryShader) ? (m_currentProgram->m_program->getGeometryShader()) : (DE_NULL));
4314 rr::RenderState state ((rr::ViewportState)(colorBuf0));
4315
4316 const rr::Renderer referenceRenderer;
4317 std::vector<rr::VertexAttrib> vertexAttribs;
4318
4319 // Gen state
4320 {
4321 const rr::PrimitiveType baseType = getPrimitiveBaseType(primitives.getPrimitiveType());
4322 const bool polygonOffsetEnabled = (baseType == rr::PRIMITIVETYPE_TRIANGLES) ? (m_polygonOffsetFillEnabled) : (false);
4323
4324 //state.cullMode = m_cullMode
4325
4326 state.fragOps.scissorTestEnabled = m_scissorEnabled;
4327 state.fragOps.scissorRectangle = rr::WindowRectangle(m_scissorBox.x(), m_scissorBox.y(), m_scissorBox.z(), m_scissorBox.w());
4328
4329 state.fragOps.numStencilBits = stencilBits;
4330 state.fragOps.stencilTestEnabled = m_stencilTestEnabled;
4331
4332 for (int faceType = 0; faceType < rr::FACETYPE_LAST; faceType++)
4333 {
4334 state.fragOps.stencilStates[faceType].compMask = m_stencil[faceType].opMask;
4335 state.fragOps.stencilStates[faceType].writeMask = m_stencil[faceType].writeMask;
4336 state.fragOps.stencilStates[faceType].ref = m_stencil[faceType].ref;
4337 state.fragOps.stencilStates[faceType].func = sglr::rr_util::mapGLTestFunc(m_stencil[faceType].func);
4338 state.fragOps.stencilStates[faceType].sFail = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opStencilFail);
4339 state.fragOps.stencilStates[faceType].dpFail = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthFail);
4340 state.fragOps.stencilStates[faceType].dpPass = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthPass);
4341 }
4342
4343 state.fragOps.depthTestEnabled = m_depthTestEnabled;
4344 state.fragOps.depthFunc = sglr::rr_util::mapGLTestFunc(m_depthFunc);
4345 state.fragOps.depthMask = m_depthMask;
4346
4347 state.fragOps.blendMode = m_blendEnabled ? rr::BLENDMODE_STANDARD : rr::BLENDMODE_NONE;
4348 state.fragOps.blendRGBState.equation = sglr::rr_util::mapGLBlendEquation(m_blendModeRGB);
4349 state.fragOps.blendRGBState.srcFunc = sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcRGB);
4350 state.fragOps.blendRGBState.dstFunc = sglr::rr_util::mapGLBlendFunc(m_blendFactorDstRGB);
4351 state.fragOps.blendAState.equation = sglr::rr_util::mapGLBlendEquation(m_blendModeAlpha);
4352 state.fragOps.blendAState.srcFunc = sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcAlpha);
4353 state.fragOps.blendAState.dstFunc = sglr::rr_util::mapGLBlendFunc(m_blendFactorDstAlpha);
4354 state.fragOps.blendColor = m_blendColor;
4355
4356 state.fragOps.sRGBEnabled = m_sRGBUpdateEnabled;
4357
4358 state.fragOps.colorMask = m_colorMask;
4359
4360 state.fragOps.depthClampEnabled = m_depthClampEnabled;
4361
4362 state.viewport.rect = rr::WindowRectangle(m_viewport.x(), m_viewport.y(), m_viewport.z(), m_viewport.w());
4363 state.viewport.zn = m_depthRangeNear;
4364 state.viewport.zf = m_depthRangeFar;
4365
4366 //state.point.pointSize = m_pointSize;
4367 state.line.lineWidth = m_lineWidth;
4368
4369 state.fragOps.polygonOffsetEnabled = polygonOffsetEnabled;
4370 state.fragOps.polygonOffsetFactor = m_polygonOffsetFactor;
4371 state.fragOps.polygonOffsetUnits = m_polygonOffsetUnits;
4372
4373 {
4374 const rr::IndexType indexType = primitives.getIndexType();
4375
4376 if (m_primitiveRestartFixedIndex && indexType != rr::INDEXTYPE_LAST)
4377 {
4378 state.restart.enabled = true;
4379 state.restart.restartIndex = getFixedRestartIndex(indexType);
4380 }
4381 else if (m_primitiveRestartSettableIndex)
4382 {
4383 // \note PRIMITIVE_RESTART is active for non-indexed (DrawArrays) operations too.
4384 state.restart.enabled = true;
4385 state.restart.restartIndex = m_primitiveRestartIndex;
4386 }
4387 else
4388 {
4389 state.restart.enabled = false;
4390 }
4391 }
4392
4393 state.provokingVertexConvention = (m_provokingFirstVertexConvention) ? (rr::PROVOKINGVERTEX_FIRST) : (rr::PROVOKINGVERTEX_LAST);
4394 }
4395
4396 // gen attributes
4397 {
4398 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4399
4400 vertexAttribs.resize(vao.m_arrays.size());
4401 for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4402 {
4403 if (!vao.m_arrays[ndx].enabled)
4404 {
4405 vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading with wrong type is allowed, but results are undefined
4406 vertexAttribs[ndx].generic = m_currentAttribs[ndx];
4407 }
4408 else if (vao.m_arrays[ndx].bufferDeleted)
4409 {
4410 vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading from deleted buffer, output zeros
4411 vertexAttribs[ndx].generic = tcu::Vec4(0, 0, 0, 0);
4412 }
4413 else
4414 {
4415 vertexAttribs[ndx].type = (vao.m_arrays[ndx].integer) ?
4416 (sglr::rr_util::mapGLPureIntegerVertexAttributeType(vao.m_arrays[ndx].type)) :
4417 (sglr::rr_util::mapGLFloatVertexAttributeType(vao.m_arrays[ndx].type, vao.m_arrays[ndx].normalized, vao.m_arrays[ndx].size, this->getType()));
4418 vertexAttribs[ndx].size = sglr::rr_util::mapGLSize(vao.m_arrays[ndx].size);
4419 vertexAttribs[ndx].stride = vao.m_arrays[ndx].stride;
4420 vertexAttribs[ndx].instanceDivisor = vao.m_arrays[ndx].divisor;
4421 vertexAttribs[ndx].pointer = (vao.m_arrays[ndx].bufferBinding) ? (vao.m_arrays[ndx].bufferBinding->getData() + ((const deUint8*)vao.m_arrays[ndx].pointer - (const deUint8*)DE_NULL)) : (vao.m_arrays[ndx].pointer);
4422 }
4423 }
4424 }
4425
4426 // Set shader samplers
4427 for (size_t uniformNdx = 0; uniformNdx < m_currentProgram->m_program->m_uniforms.size(); ++uniformNdx)
4428 {
4429 const int texNdx = m_currentProgram->m_program->m_uniforms[uniformNdx].value.i;
4430
4431 switch (m_currentProgram->m_program->m_uniforms[uniformNdx].type)
4432 {
4433 case glu::TYPE_SAMPLER_1D:
4434 case glu::TYPE_UINT_SAMPLER_1D:
4435 case glu::TYPE_INT_SAMPLER_1D:
4436 {
4437 rc::Texture1D* tex = DE_NULL;
4438
4439 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4440 tex = (m_textureUnits[texNdx].tex1DBinding) ? (m_textureUnits[texNdx].tex1DBinding) : (&m_textureUnits[texNdx].default1DTex);
4441
4442 if (tex && tex->isComplete())
4443 {
4444 tex->updateView();
4445 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = tex;
4446 }
4447 else
4448 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = &m_emptyTex1D;
4449
4450 break;
4451 }
4452 case glu::TYPE_SAMPLER_2D:
4453 case glu::TYPE_UINT_SAMPLER_2D:
4454 case glu::TYPE_INT_SAMPLER_2D:
4455 {
4456 rc::Texture2D* tex = DE_NULL;
4457
4458 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4459 tex = (m_textureUnits[texNdx].tex2DBinding) ? (m_textureUnits[texNdx].tex2DBinding) : (&m_textureUnits[texNdx].default2DTex);
4460
4461 if (tex && tex->isComplete())
4462 {
4463 tex->updateView();
4464 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = tex;
4465 }
4466 else
4467 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = &m_emptyTex2D;
4468
4469 break;
4470 }
4471 case glu::TYPE_SAMPLER_CUBE:
4472 case glu::TYPE_UINT_SAMPLER_CUBE:
4473 case glu::TYPE_INT_SAMPLER_CUBE:
4474 {
4475 rc::TextureCube* tex = DE_NULL;
4476
4477 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4478 tex = (m_textureUnits[texNdx].texCubeBinding) ? (m_textureUnits[texNdx].texCubeBinding) : (&m_textureUnits[texNdx].defaultCubeTex);
4479
4480 if (tex && tex->isComplete())
4481 {
4482 tex->updateView();
4483 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = tex;
4484 }
4485 else
4486 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = &m_emptyTexCube;
4487
4488 break;
4489 }
4490 case glu::TYPE_SAMPLER_2D_ARRAY:
4491 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
4492 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
4493 {
4494 rc::Texture2DArray* tex = DE_NULL;
4495
4496 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4497 tex = (m_textureUnits[texNdx].tex2DArrayBinding) ? (m_textureUnits[texNdx].tex2DArrayBinding) : (&m_textureUnits[texNdx].default2DArrayTex);
4498
4499 if (tex && tex->isComplete())
4500 {
4501 tex->updateView();
4502 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = tex;
4503 }
4504 else
4505 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = &m_emptyTex2DArray;
4506
4507 break;
4508 }
4509 case glu::TYPE_SAMPLER_3D:
4510 case glu::TYPE_UINT_SAMPLER_3D:
4511 case glu::TYPE_INT_SAMPLER_3D:
4512 {
4513 rc::Texture3D* tex = DE_NULL;
4514
4515 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4516 tex = (m_textureUnits[texNdx].tex3DBinding) ? (m_textureUnits[texNdx].tex3DBinding) : (&m_textureUnits[texNdx].default3DTex);
4517
4518 if (tex && tex->isComplete())
4519 {
4520 tex->updateView();
4521 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = tex;
4522 }
4523 else
4524 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = &m_emptyTex3D;
4525
4526 break;
4527 }
4528 case glu::TYPE_SAMPLER_CUBE_ARRAY:
4529 case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
4530 case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
4531 {
4532 rc::TextureCubeArray* tex = DE_NULL;
4533
4534 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4535 tex = (m_textureUnits[texNdx].texCubeArrayBinding) ? (m_textureUnits[texNdx].texCubeArrayBinding) : (&m_textureUnits[texNdx].defaultCubeArrayTex);
4536
4537 if (tex && tex->isComplete())
4538 {
4539 tex->updateView();
4540 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = tex;
4541 }
4542 else
4543 m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = &m_emptyTexCubeArray;
4544
4545 break;
4546 }
4547 default:
4548 // nothing
4549 break;
4550 }
4551 }
4552
4553 referenceRenderer.drawInstanced(rr::DrawCommand(state, renderTarget, program, (int)vertexAttribs.size(), &vertexAttribs[0], primitives), instanceCount);
4554 }
4555
createProgram(ShaderProgram * program)4556 deUint32 ReferenceContext::createProgram (ShaderProgram* program)
4557 {
4558 int name = m_programs.allocateName();
4559
4560 m_programs.insert(new rc::ShaderProgramObjectContainer(name, program));
4561
4562 return name;
4563 }
4564
useProgram(deUint32 program)4565 void ReferenceContext::useProgram (deUint32 program)
4566 {
4567 rc::ShaderProgramObjectContainer* shaderProg = DE_NULL;
4568 rc::ShaderProgramObjectContainer* programToBeDeleted = DE_NULL;
4569
4570 if (program)
4571 {
4572 shaderProg = m_programs.find(program);
4573
4574 // shader has not been linked
4575 if (!shaderProg || shaderProg->m_deleteFlag)
4576 RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4577 }
4578
4579 if (m_currentProgram && m_currentProgram->m_deleteFlag)
4580 programToBeDeleted = m_currentProgram;
4581
4582 m_currentProgram = shaderProg;
4583
4584 if (programToBeDeleted)
4585 {
4586 DE_ASSERT(programToBeDeleted->getRefCount() == 1);
4587 deleteProgramObject(programToBeDeleted);
4588 }
4589 }
4590
deleteProgram(deUint32 program)4591 void ReferenceContext::deleteProgram (deUint32 program)
4592 {
4593 if (!program)
4594 return;
4595
4596 rc::ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
4597 if (shaderProg)
4598 {
4599 if (shaderProg == m_currentProgram)
4600 {
4601 m_currentProgram->m_deleteFlag = true;
4602 }
4603 else
4604 {
4605 DE_ASSERT(shaderProg->getRefCount() == 1);
4606 m_programs.releaseReference(shaderProg);
4607 }
4608 }
4609 }
4610
readPixels(int x,int y,int width,int height,deUint32 format,deUint32 type,void * data)4611 void ReferenceContext::readPixels (int x, int y, int width, int height, deUint32 format, deUint32 type, void* data)
4612 {
4613 rr::MultisamplePixelBufferAccess src = getReadColorbuffer();
4614 TextureFormat transferFmt;
4615
4616 // Map transfer format.
4617 transferFmt = glu::mapGLTransferFormat(format, type);
4618 RC_IF_ERROR(transferFmt.order == TextureFormat::CHANNELORDER_LAST ||
4619 transferFmt.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
4620
4621 // Clamp input values
4622 const int copyX = deClamp32(x, 0, src.raw().getHeight());
4623 const int copyY = deClamp32(y, 0, src.raw().getDepth());
4624 const int copyWidth = deClamp32(width, 0, src.raw().getHeight()-x);
4625 const int copyHeight = deClamp32(height, 0, src.raw().getDepth()-y);
4626
4627 PixelBufferAccess dst(transferFmt, width, height, 1, deAlign32(width*transferFmt.getPixelSize(), m_pixelPackAlignment), 0, getPixelPackPtr(data));
4628 rr::resolveMultisampleColorBuffer(tcu::getSubregion(dst, 0, 0, copyWidth, copyHeight), rr::getSubregion(src, copyX, copyY, copyWidth, copyHeight));
4629 }
4630
getError(void)4631 deUint32 ReferenceContext::getError (void)
4632 {
4633 deUint32 err = m_lastError;
4634 m_lastError = GL_NO_ERROR;
4635 return err;
4636 }
4637
finish(void)4638 void ReferenceContext::finish (void)
4639 {
4640 }
4641
setError(deUint32 error)4642 inline void ReferenceContext::setError (deUint32 error)
4643 {
4644 if (m_lastError == GL_NO_ERROR)
4645 m_lastError = error;
4646 }
4647
getIntegerv(deUint32 pname,int * param)4648 void ReferenceContext::getIntegerv (deUint32 pname, int* param)
4649 {
4650 switch (pname)
4651 {
4652 case GL_MAX_TEXTURE_SIZE: *param = m_limits.maxTexture2DSize; break;
4653 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *param = m_limits.maxTextureCubeSize; break;
4654 case GL_MAX_ARRAY_TEXTURE_LAYERS: *param = m_limits.maxTexture2DArrayLayers; break;
4655 case GL_MAX_3D_TEXTURE_SIZE: *param = m_limits.maxTexture3DSize; break;
4656 case GL_MAX_RENDERBUFFER_SIZE: *param = m_limits.maxRenderbufferSize; break;
4657 case GL_MAX_TEXTURE_IMAGE_UNITS: *param = m_limits.maxTextureImageUnits; break;
4658 case GL_MAX_VERTEX_ATTRIBS: *param = m_limits.maxVertexAttribs; break;
4659
4660 default:
4661 setError(GL_INVALID_ENUM);
4662 break;
4663 }
4664 }
4665
getString(deUint32 pname)4666 const char* ReferenceContext::getString (deUint32 pname)
4667 {
4668 switch (pname)
4669 {
4670 case GL_EXTENSIONS: return m_limits.extensionStr.c_str();
4671
4672 default:
4673 setError(GL_INVALID_ENUM);
4674 return DE_NULL;
4675 }
4676 }
4677
4678 namespace rc
4679 {
4680
TextureLevelArray(void)4681 TextureLevelArray::TextureLevelArray (void)
4682 {
4683 deMemset(&m_data[0], 0, sizeof(m_data));
4684 }
4685
~TextureLevelArray(void)4686 TextureLevelArray::~TextureLevelArray (void)
4687 {
4688 clear();
4689 }
4690
clear(void)4691 void TextureLevelArray::clear (void)
4692 {
4693 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_data) == DE_LENGTH_OF_ARRAY(m_access));
4694
4695 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(m_data); ndx++)
4696 {
4697 delete[] m_data[ndx];
4698
4699 m_data[ndx] = DE_NULL;
4700 m_access[ndx] = PixelBufferAccess();
4701 }
4702 }
4703
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int depth)4704 void TextureLevelArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
4705 {
4706 const int dataSize = format.getPixelSize()*width*height*depth;
4707
4708 DE_ASSERT(level < DE_LENGTH_OF_ARRAY(m_data));
4709
4710 if (hasLevel(level))
4711 clearLevel(level);
4712
4713 m_data[level] = new deUint8[dataSize];
4714 m_access[level] = PixelBufferAccess(format, width, height, depth, m_data[level]);
4715 }
4716
clearLevel(int level)4717 void TextureLevelArray::clearLevel (int level)
4718 {
4719 DE_ASSERT(level < DE_LENGTH_OF_ARRAY(m_data));
4720
4721 delete[] m_data[level];
4722
4723 m_data[level] = DE_NULL;
4724 m_access[level] = PixelBufferAccess();
4725 }
4726
Texture(deUint32 name,Type type)4727 Texture::Texture (deUint32 name, Type type)
4728 : NamedObject (name)
4729 , m_type (type)
4730 , m_immutable (false)
4731 , m_sampler (tcu::Sampler::REPEAT_GL,
4732 tcu::Sampler::REPEAT_GL,
4733 tcu::Sampler::REPEAT_GL,
4734 tcu::Sampler::NEAREST_MIPMAP_LINEAR,
4735 tcu::Sampler::LINEAR,
4736 0.0f, // LOD threshold
4737 true, // normalized coords
4738 tcu::Sampler::COMPAREMODE_NONE,
4739 0, // cmp channel ndx
4740 tcu::Vec4(0.0f), // border color
4741 true // seamless cube map \todo [2014-02-19 pyry] Default value ok?
4742 )
4743 , m_baseLevel (0)
4744 , m_maxLevel (1000)
4745 {
4746 }
4747
Texture1D(deUint32 name)4748 Texture1D::Texture1D (deUint32 name)
4749 : Texture (name, TYPE_1D)
4750 , m_view (0, DE_NULL)
4751 {
4752 }
4753
~Texture1D(void)4754 Texture1D::~Texture1D (void)
4755 {
4756 }
4757
allocLevel(int level,const tcu::TextureFormat & format,int width)4758 void Texture1D::allocLevel (int level, const tcu::TextureFormat& format, int width)
4759 {
4760 m_levels.allocLevel(level, format, width, 1, 1);
4761 }
4762
isComplete(void) const4763 bool Texture1D::isComplete (void) const
4764 {
4765 const int baseLevel = getBaseLevel();
4766
4767 if (hasLevel(baseLevel))
4768 {
4769 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
4770 const bool mipmap = isMipmapFilter(getSampler().minFilter);
4771
4772 if (mipmap)
4773 {
4774 const TextureFormat& format = level0.getFormat();
4775 const int w = level0.getWidth();
4776 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(w));
4777
4778 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4779 {
4780 if (hasLevel(baseLevel+levelNdx))
4781 {
4782 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
4783 const int expectedW = getMipLevelSize(w, levelNdx);
4784
4785 if (level.getWidth() != expectedW ||
4786 level.getFormat() != format)
4787 return false;
4788 }
4789 else
4790 return false;
4791 }
4792 }
4793
4794 return true;
4795 }
4796 else
4797 return false;
4798 }
4799
sample(float s,float lod) const4800 tcu::Vec4 Texture1D::sample (float s, float lod) const
4801 {
4802 return m_view.sample(getSampler(), s, 0.0f, lod);
4803 }
4804
sample4(tcu::Vec4 output[4],const float packetTexcoords[4],float lodBias) const4805 void Texture1D::sample4 (tcu::Vec4 output[4], const float packetTexcoords[4], float lodBias) const
4806 {
4807 const int texWidth = m_view.getWidth();
4808
4809 const float dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4810 const float dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4811 const float dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4812 const float dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4813
4814 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4815 {
4816 const float& dFdx = (fragNdx > 2) ? dFdx1 : dFdx0;
4817 const float& dFdy = (fragNdx % 2) ? dFdy1 : dFdy0;
4818
4819 const float mu = de::max(de::abs(dFdx), de::abs(dFdy));
4820 const float p = mu * texWidth;
4821
4822 const float lod = deFloatLog2(p) + lodBias;
4823
4824 output[fragNdx] = sample(packetTexcoords[fragNdx], lod);
4825 }
4826 }
4827
updateView(void)4828 void Texture1D::updateView (void)
4829 {
4830 const int baseLevel = getBaseLevel();
4831
4832 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4833 {
4834 const int width = getLevel(baseLevel).getWidth();
4835 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
4836 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(width)) : 1;
4837
4838 m_view = tcu::Texture2DView(numLevels, m_levels.getLevels() + baseLevel);
4839 }
4840 else
4841 m_view = tcu::Texture2DView(0, DE_NULL);
4842 }
4843
Texture2D(deUint32 name)4844 Texture2D::Texture2D (deUint32 name)
4845 : Texture (name, TYPE_2D)
4846 , m_view (0, DE_NULL)
4847 {
4848 }
4849
~Texture2D(void)4850 Texture2D::~Texture2D (void)
4851 {
4852 }
4853
allocLevel(int level,const tcu::TextureFormat & format,int width,int height)4854 void Texture2D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height)
4855 {
4856 m_levels.allocLevel(level, format, width, height, 1);
4857 }
4858
isComplete(void) const4859 bool Texture2D::isComplete (void) const
4860 {
4861 const int baseLevel = getBaseLevel();
4862
4863 if (hasLevel(baseLevel))
4864 {
4865 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
4866 const bool mipmap = isMipmapFilter(getSampler().minFilter);
4867
4868 if (mipmap)
4869 {
4870 const TextureFormat& format = level0.getFormat();
4871 const int w = level0.getWidth();
4872 const int h = level0.getHeight();
4873 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
4874
4875 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4876 {
4877 if (hasLevel(baseLevel+levelNdx))
4878 {
4879 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
4880 const int expectedW = getMipLevelSize(w, levelNdx);
4881 const int expectedH = getMipLevelSize(h, levelNdx);
4882
4883 if (level.getWidth() != expectedW ||
4884 level.getHeight() != expectedH ||
4885 level.getFormat() != format)
4886 return false;
4887 }
4888 else
4889 return false;
4890 }
4891 }
4892
4893 return true;
4894 }
4895 else
4896 return false;
4897 }
4898
updateView(void)4899 void Texture2D::updateView (void)
4900 {
4901 const int baseLevel = getBaseLevel();
4902
4903 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4904 {
4905 // Update number of levels in mipmap pyramid.
4906 const int width = getLevel(baseLevel).getWidth();
4907 const int height = getLevel(baseLevel).getHeight();
4908 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
4909 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
4910
4911 m_view = tcu::Texture2DView(numLevels, m_levels.getLevels() + baseLevel);
4912 }
4913 else
4914 m_view = tcu::Texture2DView(0, DE_NULL);
4915 }
4916
sample(float s,float t,float lod) const4917 tcu::Vec4 Texture2D::sample (float s, float t, float lod) const
4918 {
4919 return m_view.sample(getSampler(), s, t, lod);
4920 }
4921
sample4(tcu::Vec4 output[4],const tcu::Vec2 packetTexcoords[4],float lodBias) const4922 void Texture2D::sample4 (tcu::Vec4 output[4], const tcu::Vec2 packetTexcoords[4], float lodBias) const
4923 {
4924 const int texWidth = m_view.getWidth();
4925 const int texHeight = m_view.getHeight();
4926
4927 const tcu::Vec2 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4928 const tcu::Vec2 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4929 const tcu::Vec2 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4930 const tcu::Vec2 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4931
4932 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4933 {
4934 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
4935 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
4936
4937 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
4938 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
4939 const float p = de::max(mu * texWidth, mv * texHeight);
4940
4941 const float lod = deFloatLog2(p) + lodBias;
4942
4943 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), lod);
4944 }
4945 }
4946
TextureCube(deUint32 name)4947 TextureCube::TextureCube (deUint32 name)
4948 : Texture(name, TYPE_CUBE_MAP)
4949 {
4950 }
4951
~TextureCube(void)4952 TextureCube::~TextureCube (void)
4953 {
4954 }
4955
clearLevels(void)4956 void TextureCube::clearLevels (void)
4957 {
4958 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
4959 m_levels[face].clear();
4960 }
4961
allocFace(int level,tcu::CubeFace face,const tcu::TextureFormat & format,int width,int height)4962 void TextureCube::allocFace (int level, tcu::CubeFace face, const tcu::TextureFormat& format, int width, int height)
4963 {
4964 m_levels[face].allocLevel(level, format, width, height, 1);
4965 }
4966
isComplete(void) const4967 bool TextureCube::isComplete (void) const
4968 {
4969 const int baseLevel = getBaseLevel();
4970
4971 if (hasFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X))
4972 {
4973 const int width = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
4974 const int height = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getHeight();
4975 const tcu::TextureFormat& format = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getFormat();
4976 const bool mipmap = isMipmapFilter(getSampler().minFilter);
4977 const int numLevels = mipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
4978
4979 if (width != height)
4980 return false; // Non-square is not supported.
4981
4982 // \note Level 0 is always checked for consistency
4983 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
4984 {
4985 const int levelW = getMipLevelSize(width, levelNdx);
4986 const int levelH = getMipLevelSize(height, levelNdx);
4987
4988 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
4989 {
4990 if (hasFace(baseLevel+levelNdx, (tcu::CubeFace)face))
4991 {
4992 const tcu::ConstPixelBufferAccess& level = getFace(baseLevel+levelNdx, (tcu::CubeFace)face);
4993
4994 if (level.getWidth() != levelW ||
4995 level.getHeight() != levelH ||
4996 level.getFormat() != format)
4997 return false;
4998 }
4999 else
5000 return false;
5001 }
5002 }
5003
5004 return true;
5005 }
5006 else
5007 return false;
5008 }
5009
updateView(void)5010 void TextureCube::updateView (void)
5011 {
5012 const int baseLevel = getBaseLevel();
5013 const tcu::ConstPixelBufferAccess* faces[tcu::CUBEFACE_LAST];
5014
5015 deMemset(&faces[0], 0, sizeof(faces));
5016
5017 if (isComplete())
5018 {
5019 const int size = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
5020 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
5021 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(size)) : 1;
5022
5023 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
5024 faces[face] = m_levels[face].getLevels() + baseLevel;
5025
5026 m_view = tcu::TextureCubeView(numLevels, faces);
5027 }
5028 else
5029 m_view = tcu::TextureCubeView(0, faces);
5030 }
5031
sample(float s,float t,float p,float lod) const5032 tcu::Vec4 TextureCube::sample (float s, float t, float p, float lod) const
5033 {
5034 return m_view.sample(getSampler(), s, t, p, lod);
5035 }
5036
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5037 void TextureCube::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5038 {
5039 const int cubeSide = m_view.getSize();
5040
5041 // Each tex coord might be in a different face.
5042
5043 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5044 {
5045 const tcu::CubeFace face = tcu::selectCubeFace(packetTexcoords[fragNdx]);
5046 const tcu::Vec2 coords[4] =
5047 {
5048 tcu::projectToFace(face, packetTexcoords[0]),
5049 tcu::projectToFace(face, packetTexcoords[1]),
5050 tcu::projectToFace(face, packetTexcoords[2]),
5051 tcu::projectToFace(face, packetTexcoords[3]),
5052 };
5053
5054 const tcu::Vec2 dFdx0 = coords[1] - coords[0];
5055 const tcu::Vec2 dFdx1 = coords[3] - coords[2];
5056 const tcu::Vec2 dFdy0 = coords[2] - coords[0];
5057 const tcu::Vec2 dFdy1 = coords[3] - coords[1];
5058
5059 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5060 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5061
5062 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5063 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5064 const float p = de::max(mu * cubeSide, mv * cubeSide);
5065
5066 const float lod = deFloatLog2(p) + lodBias;
5067
5068 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5069 }
5070 }
5071
Texture2DArray(deUint32 name)5072 Texture2DArray::Texture2DArray (deUint32 name)
5073 : Texture (name, TYPE_2D_ARRAY)
5074 , m_view (0, DE_NULL)
5075 {
5076 }
5077
~Texture2DArray(void)5078 Texture2DArray::~Texture2DArray (void)
5079 {
5080 }
5081
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int numLayers)5082 void Texture2DArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5083 {
5084 m_levels.allocLevel(level, format, width, height, numLayers);
5085 }
5086
isComplete(void) const5087 bool Texture2DArray::isComplete (void) const
5088 {
5089 const int baseLevel = getBaseLevel();
5090
5091 if (hasLevel(baseLevel))
5092 {
5093 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
5094 const bool mipmap = isMipmapFilter(getSampler().minFilter);
5095
5096 if (mipmap)
5097 {
5098 const TextureFormat& format = level0.getFormat();
5099 const int w = level0.getWidth();
5100 const int h = level0.getHeight();
5101 const int numLayers = level0.getDepth();
5102 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5103
5104 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5105 {
5106 if (hasLevel(baseLevel+levelNdx))
5107 {
5108 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
5109 const int expectedW = getMipLevelSize(w, levelNdx);
5110 const int expectedH = getMipLevelSize(h, levelNdx);
5111
5112 if (level.getWidth() != expectedW ||
5113 level.getHeight() != expectedH ||
5114 level.getDepth() != numLayers ||
5115 level.getFormat() != format)
5116 return false;
5117 }
5118 else
5119 return false;
5120 }
5121 }
5122
5123 return true;
5124 }
5125 else
5126 return false;
5127 }
5128
updateView(void)5129 void Texture2DArray::updateView (void)
5130 {
5131 const int baseLevel = getBaseLevel();
5132
5133 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5134 {
5135 const int width = getLevel(baseLevel).getWidth();
5136 const int height = getLevel(baseLevel).getHeight();
5137 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
5138 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5139
5140 m_view = tcu::Texture2DArrayView(numLevels, m_levels.getLevels() + baseLevel);
5141 }
5142 else
5143 m_view = tcu::Texture2DArrayView(0, DE_NULL);
5144 }
5145
sample(float s,float t,float r,float lod) const5146 tcu::Vec4 Texture2DArray::sample (float s, float t, float r, float lod) const
5147 {
5148 return m_view.sample(getSampler(), s, t, r, lod);
5149 }
5150
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5151 void Texture2DArray::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5152 {
5153 const int texWidth = m_view.getWidth();
5154 const int texHeight = m_view.getHeight();
5155
5156 const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5157 const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5158 const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5159 const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5160
5161 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5162 {
5163 const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5164 const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5165
5166 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5167 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5168 const float p = de::max(mu * texWidth, mv * texHeight);
5169
5170 const float lod = deFloatLog2(p) + lodBias;
5171
5172 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5173 }
5174 }
5175
TextureCubeArray(deUint32 name)5176 TextureCubeArray::TextureCubeArray (deUint32 name)
5177 : Texture (name, TYPE_CUBE_MAP_ARRAY)
5178 , m_view (0, DE_NULL)
5179 {
5180 }
5181
~TextureCubeArray(void)5182 TextureCubeArray::~TextureCubeArray (void)
5183 {
5184 }
5185
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int numLayers)5186 void TextureCubeArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5187 {
5188 DE_ASSERT(numLayers % 6 == 0);
5189 m_levels.allocLevel(level, format, width, height, numLayers);
5190 }
5191
isComplete(void) const5192 bool TextureCubeArray::isComplete (void) const
5193 {
5194 const int baseLevel = getBaseLevel();
5195
5196 if (hasLevel(baseLevel))
5197 {
5198 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
5199 const bool mipmap = isMipmapFilter(getSampler().minFilter);
5200
5201 if (mipmap)
5202 {
5203 const TextureFormat& format = level0.getFormat();
5204 const int w = level0.getWidth();
5205 const int h = level0.getHeight();
5206 const int numLayers = level0.getDepth();
5207 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5208
5209 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5210 {
5211 if (hasLevel(baseLevel+levelNdx))
5212 {
5213 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
5214 const int expectedW = getMipLevelSize(w, levelNdx);
5215 const int expectedH = getMipLevelSize(h, levelNdx);
5216
5217 if (level.getWidth() != expectedW ||
5218 level.getHeight() != expectedH ||
5219 level.getDepth() != numLayers ||
5220 level.getFormat() != format)
5221 return false;
5222 }
5223 else
5224 return false;
5225 }
5226 }
5227
5228 return true;
5229 }
5230 else
5231 return false;
5232 }
5233
updateView(void)5234 void TextureCubeArray::updateView (void)
5235 {
5236 const int baseLevel = getBaseLevel();
5237
5238 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5239 {
5240 const int width = getLevel(baseLevel).getWidth();
5241 const int height = getLevel(baseLevel).getHeight();
5242 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
5243 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5244
5245 m_view = tcu::TextureCubeArrayView(numLevels, m_levels.getLevels() + baseLevel);
5246 }
5247 else
5248 m_view = tcu::TextureCubeArrayView(0, DE_NULL);
5249 }
5250
sample(float s,float t,float r,float q,float lod) const5251 tcu::Vec4 TextureCubeArray::sample (float s, float t, float r, float q, float lod) const
5252 {
5253 return m_view.sample(getSampler(), s, t, r, q, lod);
5254 }
5255
sample4(tcu::Vec4 output[4],const tcu::Vec4 packetTexcoords[4],float lodBias) const5256 void TextureCubeArray::sample4 (tcu::Vec4 output[4], const tcu::Vec4 packetTexcoords[4], float lodBias) const
5257 {
5258 const int cubeSide = m_view.getSize();
5259 const tcu::Vec3 cubeCoords[4] =
5260 {
5261 packetTexcoords[0].toWidth<3>(),
5262 packetTexcoords[1].toWidth<3>(),
5263 packetTexcoords[2].toWidth<3>(),
5264 packetTexcoords[3].toWidth<3>()
5265 };
5266
5267 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5268 {
5269 const tcu::CubeFace face = tcu::selectCubeFace(cubeCoords[fragNdx]);
5270 const tcu::Vec2 faceCoords[4] =
5271 {
5272 tcu::projectToFace(face, cubeCoords[0]),
5273 tcu::projectToFace(face, cubeCoords[1]),
5274 tcu::projectToFace(face, cubeCoords[2]),
5275 tcu::projectToFace(face, cubeCoords[3]),
5276 };
5277
5278 const tcu::Vec2 dFdx0 = faceCoords[1] - faceCoords[0];
5279 const tcu::Vec2 dFdx1 = faceCoords[3] - faceCoords[2];
5280 const tcu::Vec2 dFdy0 = faceCoords[2] - faceCoords[0];
5281 const tcu::Vec2 dFdy1 = faceCoords[3] - faceCoords[1];
5282
5283 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5284 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5285
5286 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5287 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5288 const float p = de::max(mu * cubeSide, mv * cubeSide);
5289
5290 const float lod = deFloatLog2(p) + lodBias;
5291
5292 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), packetTexcoords[fragNdx].w(), lod);
5293 }
5294 }
5295
Texture3D(deUint32 name)5296 Texture3D::Texture3D (deUint32 name)
5297 : Texture (name, TYPE_3D)
5298 , m_view (0, DE_NULL)
5299 {
5300 }
5301
~Texture3D(void)5302 Texture3D::~Texture3D (void)
5303 {
5304 }
5305
allocLevel(int level,const tcu::TextureFormat & format,int width,int height,int depth)5306 void Texture3D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
5307 {
5308 m_levels.allocLevel(level, format, width, height, depth);
5309 }
5310
isComplete(void) const5311 bool Texture3D::isComplete (void) const
5312 {
5313 const int baseLevel = getBaseLevel();
5314
5315 if (hasLevel(baseLevel))
5316 {
5317 const tcu::ConstPixelBufferAccess& level0 = getLevel(baseLevel);
5318 const bool mipmap = isMipmapFilter(getSampler().minFilter);
5319
5320 if (mipmap)
5321 {
5322 const TextureFormat& format = level0.getFormat();
5323 const int w = level0.getWidth();
5324 const int h = level0.getHeight();
5325 const int d = level0.getDepth();
5326 const int numLevels = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(w, h, d));
5327
5328 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5329 {
5330 if (hasLevel(baseLevel+levelNdx))
5331 {
5332 const tcu::ConstPixelBufferAccess& level = getLevel(baseLevel+levelNdx);
5333 const int expectedW = getMipLevelSize(w, levelNdx);
5334 const int expectedH = getMipLevelSize(h, levelNdx);
5335 const int expectedD = getMipLevelSize(d, levelNdx);
5336
5337 if (level.getWidth() != expectedW ||
5338 level.getHeight() != expectedH ||
5339 level.getDepth() != expectedD ||
5340 level.getFormat() != format)
5341 return false;
5342 }
5343 else
5344 return false;
5345 }
5346 }
5347
5348 return true;
5349 }
5350 else
5351 return false;
5352 }
5353
sample(float s,float t,float r,float lod) const5354 tcu::Vec4 Texture3D::sample (float s, float t, float r, float lod) const
5355 {
5356 return m_view.sample(getSampler(), s, t, r, lod);
5357 }
5358
sample4(tcu::Vec4 output[4],const tcu::Vec3 packetTexcoords[4],float lodBias) const5359 void Texture3D::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5360 {
5361 const int texWidth = m_view.getWidth();
5362 const int texHeight = m_view.getHeight();
5363 const int texDepth = m_view.getDepth();
5364
5365 const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5366 const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5367 const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5368 const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5369
5370 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5371 {
5372 const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5373 const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5374
5375 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5376 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5377 const float mw = de::max(de::abs(dFdx.z()), de::abs(dFdy.z()));
5378 const float p = de::max(de::max(mu * texWidth, mv * texHeight), mw * texDepth);
5379
5380 const float lod = deFloatLog2(p) + lodBias;
5381
5382 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5383 }
5384 }
5385
updateView(void)5386 void Texture3D::updateView (void)
5387 {
5388 const int baseLevel = getBaseLevel();
5389
5390 if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5391 {
5392 const int width = getLevel(baseLevel).getWidth();
5393 const int height = getLevel(baseLevel).getHeight();
5394 const int depth = getLevel(baseLevel).getDepth();
5395 const bool isMipmap = isMipmapFilter(getSampler().minFilter);
5396 const int numLevels = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(width, height, depth)) : 1;
5397
5398 m_view = tcu::Texture3DView(numLevels, m_levels.getLevels() + baseLevel);
5399 }
5400 else
5401 m_view = tcu::Texture3DView(0, DE_NULL);
5402 }
5403
Renderbuffer(deUint32 name)5404 Renderbuffer::Renderbuffer (deUint32 name)
5405 : NamedObject (name)
5406 {
5407 }
5408
~Renderbuffer(void)5409 Renderbuffer::~Renderbuffer (void)
5410 {
5411 }
5412
setStorage(const TextureFormat & format,int width,int height)5413 void Renderbuffer::setStorage (const TextureFormat& format, int width, int height)
5414 {
5415 m_data.setStorage(format, width, height);
5416 }
5417
Framebuffer(deUint32 name)5418 Framebuffer::Framebuffer (deUint32 name)
5419 : NamedObject(name)
5420 {
5421 }
5422
~Framebuffer(void)5423 Framebuffer::~Framebuffer (void)
5424 {
5425 }
5426
VertexArray(deUint32 name,int maxVertexAttribs)5427 VertexArray::VertexArray (deUint32 name, int maxVertexAttribs)
5428 : NamedObject (name)
5429 , m_elementArrayBufferBinding (DE_NULL)
5430 , m_arrays (maxVertexAttribs)
5431 {
5432 for (int i = 0; i < maxVertexAttribs; ++i)
5433 {
5434 m_arrays[i].enabled = false;
5435 m_arrays[i].size = 4;
5436 m_arrays[i].stride = 0;
5437 m_arrays[i].type = GL_FLOAT;
5438 m_arrays[i].normalized = false;
5439 m_arrays[i].integer = false;
5440 m_arrays[i].divisor = 0;
5441 m_arrays[i].bufferDeleted = false;
5442 m_arrays[i].bufferBinding = DE_NULL;
5443 m_arrays[i].pointer = DE_NULL;
5444 }
5445 }
5446
ShaderProgramObjectContainer(deUint32 name,ShaderProgram * program)5447 ShaderProgramObjectContainer::ShaderProgramObjectContainer (deUint32 name, ShaderProgram* program)
5448 : NamedObject (name)
5449 , m_program (program)
5450 , m_deleteFlag (false)
5451 {
5452 }
5453
~ShaderProgramObjectContainer(void)5454 ShaderProgramObjectContainer::~ShaderProgramObjectContainer (void)
5455 {
5456 }
5457
5458 } // rc
5459 } // sglr
5460