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