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