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