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