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