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