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