1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9 #include "gl/GrGLInterface.h" 10 #include "GrGLDefines.h" 11 #include "SkTDArray.h" 12 #include "GrGLNoOpInterface.h" 13 #include "SkTLS.h" 14 15 class BufferObj { 16 public: 17 SK_DECLARE_INST_COUNT_ROOT(BufferObj); 18 19 BufferObj(GrGLuint id) : fID(id), fDataPtr(NULL), fSize(0), fMapped(false) { 20 } 21 ~BufferObj() { SkDELETE_ARRAY(fDataPtr); } 22 23 void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) { 24 if (fDataPtr) { 25 SkASSERT(0 != fSize); 26 SkDELETE_ARRAY(fDataPtr); 27 } 28 29 fSize = size; 30 fDataPtr = SkNEW_ARRAY(char, size); 31 } 32 33 GrGLuint id() const { return fID; } 34 GrGLchar* dataPtr() { return fDataPtr; } 35 GrGLsizeiptr size() const { return fSize; } 36 37 void setMapped(bool mapped) { fMapped = mapped; } 38 bool mapped() const { return fMapped; } 39 40 private: 41 GrGLuint fID; 42 GrGLchar* fDataPtr; 43 GrGLsizeiptr fSize; // size in bytes 44 bool fMapped; 45 }; 46 47 // This class maintains a sparsely populated array of buffer pointers. 48 class BufferManager { 49 public: 50 SK_DECLARE_INST_COUNT_ROOT(BufferManager); 51 52 BufferManager() : fFreeListHead(kFreeListEnd) {} 53 54 ~BufferManager() { 55 // NULL out the entries that are really free list links rather than ptrs before deleting. 56 intptr_t curr = fFreeListHead; 57 while (kFreeListEnd != curr) { 58 intptr_t next = reinterpret_cast<intptr_t>(fBuffers[SkToS32(curr)]); 59 fBuffers[SkToS32(curr)] = NULL; 60 curr = next; 61 } 62 63 fBuffers.deleteAll(); 64 } 65 66 BufferObj* lookUp(GrGLuint id) { 67 BufferObj* buffer = fBuffers[id]; 68 SkASSERT(buffer && buffer->id() == id); 69 return buffer; 70 } 71 72 BufferObj* create() { 73 GrGLuint id; 74 BufferObj* buffer; 75 76 if (kFreeListEnd == fFreeListHead) { 77 // no free slots - create a new one 78 id = fBuffers.count(); 79 buffer = SkNEW_ARGS(BufferObj, (id)); 80 *fBuffers.append() = buffer; 81 } else { 82 // grab the head of the free list and advance the head to the next free slot. 83 id = static_cast<GrGLuint>(fFreeListHead); 84 fFreeListHead = reinterpret_cast<intptr_t>(fBuffers[id]); 85 86 buffer = SkNEW_ARGS(BufferObj, (id)); 87 fBuffers[id] = buffer; 88 } 89 90 return buffer; 91 } 92 93 void free(BufferObj* buffer) { 94 SkASSERT(fBuffers.count() > 0); 95 96 GrGLuint id = buffer->id(); 97 SkDELETE(buffer); 98 99 fBuffers[id] = reinterpret_cast<BufferObj*>(fFreeListHead); 100 fFreeListHead = id; 101 } 102 103 private: 104 static const intptr_t kFreeListEnd = -1; 105 // Index of the first entry of fBuffers in the free list. Free slots in fBuffers are indices to 106 // the next free slot. The last free slot has a value of kFreeListEnd. 107 intptr_t fFreeListHead; 108 SkTDArray<BufferObj*> fBuffers; 109 }; 110 111 /** 112 * The global-to-thread state object for the null interface. All null interfaces on the 113 * same thread currently share one of these. This means two null contexts on the same thread 114 * can interfere with each other. It may make sense to more integrate this into SkNullGLContext 115 * and use it's makeCurrent mechanism. 116 */ 117 struct ThreadContext { 118 public: 119 SK_DECLARE_INST_COUNT_ROOT(ThreadContext); 120 121 BufferManager fBufferManager; 122 GrGLuint fCurrArrayBuffer; 123 GrGLuint fCurrElementArrayBuffer; 124 GrGLuint fCurrProgramID; 125 GrGLuint fCurrShaderID; 126 127 static ThreadContext* Get() { 128 return reinterpret_cast<ThreadContext*>(SkTLS::Get(Create, Delete)); 129 } 130 131 ThreadContext() 132 : fCurrArrayBuffer(0) 133 , fCurrElementArrayBuffer(0) 134 , fCurrProgramID(0) 135 , fCurrShaderID(0) {} 136 137 private: 138 static void* Create() { return SkNEW(ThreadContext ); } 139 static void Delete(void* context) { SkDELETE(reinterpret_cast<ThreadContext *>(context)); } 140 }; 141 142 // Functions not declared in GrGLBogusInterface.h (not common with the Debug GL interface). 143 144 namespace { // added to suppress 'no previous prototype' warning 145 146 GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {} 147 GrGLvoid GR_GL_FUNCTION_TYPE nullGLAttachShader(GrGLuint program, GrGLuint shader) {} 148 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBeginQuery(GrGLenum target, GrGLuint id) {} 149 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindAttribLocation(GrGLuint program, GrGLuint index, const char* name) {} 150 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindTexture(GrGLenum target, GrGLuint texture) {} 151 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindVertexArray(GrGLuint id) {} 152 153 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenBuffers(GrGLsizei n, GrGLuint* ids) { 154 ThreadContext* ctx = ThreadContext::Get(); 155 for (int i = 0; i < n; ++i) { 156 BufferObj* buffer = ctx->fBufferManager.create(); 157 ids[i] = buffer->id(); 158 } 159 } 160 161 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenerateMipmap(GrGLenum target) {} 162 163 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBufferData(GrGLenum target, 164 GrGLsizeiptr size, 165 const GrGLvoid* data, 166 GrGLenum usage) { 167 ThreadContext* ctx = ThreadContext::Get(); 168 GrGLuint id = 0; 169 170 switch (target) { 171 case GR_GL_ARRAY_BUFFER: 172 id = ctx->fCurrArrayBuffer; 173 break; 174 case GR_GL_ELEMENT_ARRAY_BUFFER: 175 id = ctx->fCurrElementArrayBuffer; 176 break; 177 default: 178 SkFAIL("Unexpected target to nullGLBufferData"); 179 break; 180 } 181 182 if (id > 0) { 183 BufferObj* buffer = ctx->fBufferManager.lookUp(id); 184 buffer->allocate(size, (const GrGLchar*) data); 185 } 186 } 187 188 GrGLvoid GR_GL_FUNCTION_TYPE nullGLPixelStorei(GrGLenum pname, GrGLint param) {} 189 GrGLvoid GR_GL_FUNCTION_TYPE nullGLReadPixels(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels) {} 190 GrGLvoid GR_GL_FUNCTION_TYPE nullGLUseProgram(GrGLuint program) {} 191 GrGLvoid GR_GL_FUNCTION_TYPE nullGLViewport(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {} 192 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindFramebuffer(GrGLenum target, GrGLuint framebuffer) {} 193 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {} 194 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {} 195 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {} 196 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {} 197 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {} 198 199 GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateProgram() { 200 return ++ThreadContext::Get()->fCurrProgramID; 201 } 202 203 GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateShader(GrGLenum type) { 204 return ++ThreadContext::Get()->fCurrShaderID; 205 } 206 207 // same delete used for shaders and programs 208 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDelete(GrGLuint program) { 209 } 210 211 GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindBuffer(GrGLenum target, GrGLuint buffer) { 212 ThreadContext* ctx = ThreadContext::Get(); 213 switch (target) { 214 case GR_GL_ARRAY_BUFFER: 215 ctx->fCurrArrayBuffer = buffer; 216 break; 217 case GR_GL_ELEMENT_ARRAY_BUFFER: 218 ctx->fCurrElementArrayBuffer = buffer; 219 break; 220 } 221 } 222 223 // deleting a bound buffer has the side effect of binding 0 224 GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteBuffers(GrGLsizei n, const GrGLuint* ids) { 225 ThreadContext* ctx = ThreadContext::Get(); 226 for (int i = 0; i < n; ++i) { 227 if (ids[i] == ctx->fCurrArrayBuffer) { 228 ctx->fCurrArrayBuffer = 0; 229 } 230 if (ids[i] == ctx->fCurrElementArrayBuffer) { 231 ctx->fCurrElementArrayBuffer = 0; 232 } 233 234 BufferObj* buffer = ctx->fBufferManager.lookUp(ids[i]); 235 ctx->fBufferManager.free(buffer); 236 } 237 } 238 239 GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBufferRange(GrGLenum target, GrGLintptr offset, 240 GrGLsizeiptr length, GrGLbitfield access) { 241 ThreadContext* ctx = ThreadContext::Get(); 242 GrGLuint id = 0; 243 switch (target) { 244 case GR_GL_ARRAY_BUFFER: 245 id = ctx->fCurrArrayBuffer; 246 break; 247 case GR_GL_ELEMENT_ARRAY_BUFFER: 248 id = ctx->fCurrElementArrayBuffer; 249 break; 250 } 251 252 if (id > 0) { 253 // We just ignore the offset and length here. 254 BufferObj* buffer = ctx->fBufferManager.lookUp(id); 255 SkASSERT(!buffer->mapped()); 256 buffer->setMapped(true); 257 return buffer->dataPtr(); 258 } 259 return NULL; 260 } 261 262 GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) { 263 ThreadContext* ctx = ThreadContext::Get(); 264 GrGLuint id = 0; 265 switch (target) { 266 case GR_GL_ARRAY_BUFFER: 267 id = ctx->fCurrArrayBuffer; 268 break; 269 case GR_GL_ELEMENT_ARRAY_BUFFER: 270 id = ctx->fCurrElementArrayBuffer; 271 break; 272 } 273 274 if (id > 0) { 275 BufferObj* buffer = ctx->fBufferManager.lookUp(id); 276 SkASSERT(!buffer->mapped()); 277 buffer->setMapped(true); 278 return buffer->dataPtr(); 279 } 280 281 SkASSERT(false); 282 return NULL; // no buffer bound to target 283 } 284 285 GrGLvoid GR_GL_FUNCTION_TYPE nullGLFlushMappedBufferRange(GrGLenum target, 286 GrGLintptr offset, 287 GrGLsizeiptr length) {} 288 289 290 GrGLboolean GR_GL_FUNCTION_TYPE nullGLUnmapBuffer(GrGLenum target) { 291 ThreadContext* ctx = ThreadContext::Get(); 292 GrGLuint id = 0; 293 switch (target) { 294 case GR_GL_ARRAY_BUFFER: 295 id = ctx->fCurrArrayBuffer; 296 break; 297 case GR_GL_ELEMENT_ARRAY_BUFFER: 298 id = ctx->fCurrElementArrayBuffer; 299 break; 300 } 301 if (id > 0) { 302 BufferObj* buffer = ctx->fBufferManager.lookUp(id); 303 SkASSERT(buffer->mapped()); 304 buffer->setMapped(false); 305 return GR_GL_TRUE; 306 } 307 308 GrAlwaysAssert(false); 309 return GR_GL_FALSE; // GR_GL_INVALID_OPERATION; 310 } 311 312 GrGLvoid GR_GL_FUNCTION_TYPE nullGLGetBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) { 313 ThreadContext* ctx = ThreadContext::Get(); 314 switch (pname) { 315 case GR_GL_BUFFER_MAPPED: { 316 *params = GR_GL_FALSE; 317 GrGLuint id = 0; 318 switch (target) { 319 case GR_GL_ARRAY_BUFFER: 320 id = ctx->fCurrArrayBuffer; 321 break; 322 case GR_GL_ELEMENT_ARRAY_BUFFER: 323 id = ctx->fCurrElementArrayBuffer; 324 break; 325 } 326 if (id > 0) { 327 BufferObj* buffer = ctx->fBufferManager.lookUp(id); 328 if (buffer->mapped()) { 329 *params = GR_GL_TRUE; 330 } 331 } 332 break; } 333 default: 334 SkFAIL("Unexpected pname to GetBufferParamateriv"); 335 break; 336 } 337 }; 338 339 } // end anonymous namespace 340 341 const GrGLInterface* GrGLCreateNullInterface() { 342 GrGLInterface* interface = SkNEW(GrGLInterface); 343 344 interface->fStandard = kGL_GrGLStandard; 345 346 GrGLInterface::Functions* functions = &interface->fFunctions; 347 functions->fActiveTexture = nullGLActiveTexture; 348 functions->fAttachShader = nullGLAttachShader; 349 functions->fBeginQuery = nullGLBeginQuery; 350 functions->fBindAttribLocation = nullGLBindAttribLocation; 351 functions->fBindBuffer = nullGLBindBuffer; 352 functions->fBindFragDataLocation = noOpGLBindFragDataLocation; 353 functions->fBindTexture = nullGLBindTexture; 354 functions->fBindVertexArray = nullGLBindVertexArray; 355 functions->fBlendColor = noOpGLBlendColor; 356 functions->fBlendFunc = noOpGLBlendFunc; 357 functions->fBufferData = nullGLBufferData; 358 functions->fBufferSubData = noOpGLBufferSubData; 359 functions->fClear = noOpGLClear; 360 functions->fClearColor = noOpGLClearColor; 361 functions->fClearStencil = noOpGLClearStencil; 362 functions->fColorMask = noOpGLColorMask; 363 functions->fCompileShader = noOpGLCompileShader; 364 functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D; 365 functions->fCompressedTexSubImage2D = noOpGLCompressedTexSubImage2D; 366 functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D; 367 functions->fCreateProgram = nullGLCreateProgram; 368 functions->fCreateShader = nullGLCreateShader; 369 functions->fCullFace = noOpGLCullFace; 370 functions->fDeleteBuffers = nullGLDeleteBuffers; 371 functions->fDeleteProgram = nullGLDelete; 372 functions->fDeleteQueries = noOpGLDeleteIds; 373 functions->fDeleteShader = nullGLDelete; 374 functions->fDeleteTextures = noOpGLDeleteIds; 375 functions->fDeleteVertexArrays = noOpGLDeleteIds; 376 functions->fDepthMask = noOpGLDepthMask; 377 functions->fDisable = noOpGLDisable; 378 functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray; 379 functions->fDrawArrays = noOpGLDrawArrays; 380 functions->fDrawBuffer = noOpGLDrawBuffer; 381 functions->fDrawBuffers = noOpGLDrawBuffers; 382 functions->fDrawElements = noOpGLDrawElements; 383 functions->fEnable = noOpGLEnable; 384 functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray; 385 functions->fEndQuery = noOpGLEndQuery; 386 functions->fFinish = noOpGLFinish; 387 functions->fFlush = noOpGLFlush; 388 functions->fFlushMappedBufferRange = nullGLFlushMappedBufferRange; 389 functions->fFrontFace = noOpGLFrontFace; 390 functions->fGenBuffers = nullGLGenBuffers; 391 functions->fGenerateMipmap = nullGLGenerateMipmap; 392 functions->fGenQueries = noOpGLGenIds; 393 functions->fGenTextures = noOpGLGenIds; 394 functions->fGenVertexArrays = noOpGLGenIds; 395 functions->fGetBufferParameteriv = nullGLGetBufferParameteriv; 396 functions->fGetError = noOpGLGetError; 397 functions->fGetIntegerv = noOpGLGetIntegerv; 398 functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v; 399 functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv; 400 functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v; 401 functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv; 402 functions->fGetQueryiv = noOpGLGetQueryiv; 403 functions->fGetProgramInfoLog = noOpGLGetInfoLog; 404 functions->fGetProgramiv = noOpGLGetShaderOrProgramiv; 405 functions->fGetShaderInfoLog = noOpGLGetInfoLog; 406 functions->fGetShaderiv = noOpGLGetShaderOrProgramiv; 407 functions->fGetString = noOpGLGetString; 408 functions->fGetStringi = noOpGLGetStringi; 409 functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv; 410 functions->fGetUniformLocation = noOpGLGetUniformLocation; 411 functions->fInsertEventMarker = noOpGLInsertEventMarker; 412 functions->fLineWidth = noOpGLLineWidth; 413 functions->fLinkProgram = noOpGLLinkProgram; 414 functions->fMapBuffer = nullGLMapBuffer; 415 functions->fMapBufferRange = nullGLMapBufferRange; 416 functions->fPixelStorei = nullGLPixelStorei; 417 functions->fPopGroupMarker = noOpGLPopGroupMarker; 418 functions->fPushGroupMarker = noOpGLPushGroupMarker; 419 functions->fQueryCounter = noOpGLQueryCounter; 420 functions->fReadBuffer = noOpGLReadBuffer; 421 functions->fReadPixels = nullGLReadPixels; 422 functions->fScissor = noOpGLScissor; 423 functions->fShaderSource = noOpGLShaderSource; 424 functions->fStencilFunc = noOpGLStencilFunc; 425 functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate; 426 functions->fStencilMask = noOpGLStencilMask; 427 functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate; 428 functions->fStencilOp = noOpGLStencilOp; 429 functions->fStencilOpSeparate = noOpGLStencilOpSeparate; 430 functions->fTexImage2D = noOpGLTexImage2D; 431 functions->fTexParameteri = noOpGLTexParameteri; 432 functions->fTexParameteriv = noOpGLTexParameteriv; 433 functions->fTexSubImage2D = noOpGLTexSubImage2D; 434 functions->fTexStorage2D = noOpGLTexStorage2D; 435 functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer; 436 functions->fUniform1f = noOpGLUniform1f; 437 functions->fUniform1i = noOpGLUniform1i; 438 functions->fUniform1fv = noOpGLUniform1fv; 439 functions->fUniform1iv = noOpGLUniform1iv; 440 functions->fUniform2f = noOpGLUniform2f; 441 functions->fUniform2i = noOpGLUniform2i; 442 functions->fUniform2fv = noOpGLUniform2fv; 443 functions->fUniform2iv = noOpGLUniform2iv; 444 functions->fUniform3f = noOpGLUniform3f; 445 functions->fUniform3i = noOpGLUniform3i; 446 functions->fUniform3fv = noOpGLUniform3fv; 447 functions->fUniform3iv = noOpGLUniform3iv; 448 functions->fUniform4f = noOpGLUniform4f; 449 functions->fUniform4i = noOpGLUniform4i; 450 functions->fUniform4fv = noOpGLUniform4fv; 451 functions->fUniform4iv = noOpGLUniform4iv; 452 functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv; 453 functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv; 454 functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv; 455 functions->fUnmapBuffer = nullGLUnmapBuffer; 456 functions->fUseProgram = nullGLUseProgram; 457 functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv; 458 functions->fVertexAttribPointer = noOpGLVertexAttribPointer; 459 functions->fViewport = nullGLViewport; 460 functions->fBindFramebuffer = nullGLBindFramebuffer; 461 functions->fBindRenderbuffer = nullGLBindRenderbuffer; 462 functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus; 463 functions->fDeleteFramebuffers = nullGLDeleteFramebuffers; 464 functions->fDeleteRenderbuffers = nullGLDeleteRenderbuffers; 465 functions->fFramebufferRenderbuffer = nullGLFramebufferRenderbuffer; 466 functions->fFramebufferTexture2D = nullGLFramebufferTexture2D; 467 functions->fGenFramebuffers = noOpGLGenIds; 468 functions->fGenRenderbuffers = noOpGLGenIds; 469 functions->fGetFramebufferAttachmentParameteriv = noOpGLGetFramebufferAttachmentParameteriv; 470 functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv; 471 functions->fRenderbufferStorage = noOpGLRenderbufferStorage; 472 functions->fRenderbufferStorageMultisample = noOpGLRenderbufferStorageMultisample; 473 functions->fBlitFramebuffer = noOpGLBlitFramebuffer; 474 functions->fResolveMultisampleFramebuffer = noOpGLResolveMultisampleFramebuffer; 475 functions->fMatrixLoadf = noOpGLMatrixLoadf; 476 functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity; 477 functions->fBindFragDataLocationIndexed = noOpGLBindFragDataLocationIndexed; 478 479 interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi, 480 functions->fGetIntegerv); 481 return interface; 482 } 483