blob: b330b0d94cc408e7e75b01fb8646a842e91280d8 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Context.cpp: Implements the gl::Context class, managing all GL state and performing
8// rendering operations. It is the GLES2 specific implementation of EGLContext.
9
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +000010#include "Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000014#include "main.h"
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000015#include "libEGL/Display.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000016#include "Buffer.h"
17#include "Shader.h"
18#include "Program.h"
19#include "Texture.h"
20#include "FrameBuffer.h"
21#include "RenderBuffer.h"
22#include "mathutil.h"
23#include "utilities.h"
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000024#include "geometry/backend.h"
25#include "geometry/VertexDataManager.h"
26#include "geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000027
daniel@transgaming.com86487c22010-03-11 19:41:43 +000028#undef near
29#undef far
30
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031namespace gl
32{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000033Context::Context(const egl::Config *config)
34 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035{
36 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
37 depthClearValue = 1.0f;
38 stencilClearValue = 0;
39
40 cullFace = false;
41 cullMode = GL_BACK;
42 frontFace = GL_CCW;
43 depthTest = false;
44 depthFunc = GL_LESS;
45 blend = false;
46 sourceBlendRGB = GL_ONE;
47 sourceBlendAlpha = GL_ONE;
48 destBlendRGB = GL_ZERO;
49 destBlendAlpha = GL_ZERO;
50 blendEquationRGB = GL_FUNC_ADD;
51 blendEquationAlpha = GL_FUNC_ADD;
52 blendColor.red = 0;
53 blendColor.green = 0;
54 blendColor.blue = 0;
55 blendColor.alpha = 0;
56 stencilTest = false;
57 stencilFunc = GL_ALWAYS;
58 stencilRef = 0;
59 stencilMask = -1;
60 stencilWritemask = -1;
61 stencilBackFunc = GL_ALWAYS;
62 stencilBackRef = 0;
63 stencilBackMask = - 1;
64 stencilBackWritemask = -1;
65 stencilFail = GL_KEEP;
66 stencilPassDepthFail = GL_KEEP;
67 stencilPassDepthPass = GL_KEEP;
68 stencilBackFail = GL_KEEP;
69 stencilBackPassDepthFail = GL_KEEP;
70 stencilBackPassDepthPass = GL_KEEP;
71 polygonOffsetFill = false;
72 sampleAlphaToCoverage = false;
73 sampleCoverage = false;
74 sampleCoverageValue = 1.0f;
75 sampleCoverageInvert = GL_FALSE;
76 scissorTest = false;
77 dither = true;
daniel@transgaming.com5949aa12010-03-21 04:31:15 +000078 generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000080 lineWidth = 1.0f;
81
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000082 viewportX = 0;
83 viewportY = 0;
84 viewportWidth = config->mDisplayMode.Width;
85 viewportHeight = config->mDisplayMode.Height;
86 zNear = 0.0f;
87 zFar = 1.0f;
88
89 scissorX = 0;
90 scissorY = 0;
91 scissorWidth = config->mDisplayMode.Width;
92 scissorHeight = config->mDisplayMode.Height;
93
94 colorMaskRed = true;
95 colorMaskGreen = true;
96 colorMaskBlue = true;
97 colorMaskAlpha = true;
98 depthMask = true;
99
100 // [OpenGL ES 2.0.24] section 3.7 page 83:
101 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
102 // and cube map texture state vectors respectively associated with them.
103 // In order that access to these initial textures not be lost, they are treated as texture
104 // objects all of whose names are 0.
105
106 mTexture2DZero = new Texture2D();
107 mTextureCubeMapZero = new TextureCubeMap();
108
109 mColorbufferZero = NULL;
110 mDepthbufferZero = NULL;
111 mStencilbufferZero = NULL;
112
113 activeSampler = 0;
114 arrayBuffer = 0;
115 elementArrayBuffer = 0;
116 bindTextureCubeMap(0);
117 bindTexture2D(0);
118 bindFramebuffer(0);
119 bindRenderbuffer(0);
120
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000121 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000123 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
124 {
125 samplerTexture[type][sampler] = 0;
126 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127 }
128
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000129 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
130 {
131 mIncompleteTextures[type] = NULL;
132 }
133
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134 currentProgram = 0;
135
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000136 packAlignment = 4;
137 unpackAlignment = 4;
138
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000139 mBufferBackEnd = NULL;
140 mVertexDataManager = NULL;
141
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142 mInvalidEnum = false;
143 mInvalidValue = false;
144 mInvalidOperation = false;
145 mOutOfMemory = false;
146 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000147
148 mHasBeenCurrent = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149}
150
151Context::~Context()
152{
153 currentProgram = 0;
154
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000155 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
156 {
157 delete mIncompleteTextures[type];
158 }
159
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160 delete mTexture2DZero;
161 delete mTextureCubeMapZero;
162
163 delete mColorbufferZero;
164 delete mDepthbufferZero;
165 delete mStencilbufferZero;
166
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000167 delete mBufferBackEnd;
168 delete mVertexDataManager;
169
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170 while (!mBufferMap.empty())
171 {
172 deleteBuffer(mBufferMap.begin()->first);
173 }
174
175 while (!mProgramMap.empty())
176 {
177 deleteProgram(mProgramMap.begin()->first);
178 }
179
180 while (!mShaderMap.empty())
181 {
182 deleteShader(mShaderMap.begin()->first);
183 }
184
185 while (!mFramebufferMap.empty())
186 {
187 deleteFramebuffer(mFramebufferMap.begin()->first);
188 }
189
190 while (!mRenderbufferMap.empty())
191 {
192 deleteRenderbuffer(mRenderbufferMap.begin()->first);
193 }
194
195 while (!mTextureMap.empty())
196 {
197 deleteTexture(mTextureMap.begin()->first);
198 }
199}
200
201void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
202{
203 IDirect3DDevice9 *device = display->getDevice();
204
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000205 if (!mBufferBackEnd)
206 {
207 mBufferBackEnd = new Dx9BackEnd(device);
208 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
209 }
210
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
212 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000213 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214
215 Framebuffer *framebufferZero = new Framebuffer();
216 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000217 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
218 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219
220 setFramebufferZero(framebufferZero);
221 setColorbufferZero(colorbufferZero);
222 setDepthbufferZero(depthbufferZero);
223 setStencilbufferZero(stencilbufferZero);
224
225 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
226 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
227 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
228
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000229 if(!mHasBeenCurrent)
230 {
231 viewportX = 0;
232 viewportY = 0;
233 viewportWidth = surface->getWidth();
234 viewportHeight = surface->getHeight();
235
236 scissorX = 0;
237 scissorY = 0;
238 scissorWidth = surface->getWidth();
239 scissorHeight = surface->getHeight();
240
241 mHasBeenCurrent = true;
242 }
243
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244 defaultRenderTarget->Release();
245
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000246 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000248 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249 }
250}
251
252void Context::setClearColor(float red, float green, float blue, float alpha)
253{
254 colorClearValue.red = red;
255 colorClearValue.green = green;
256 colorClearValue.blue = blue;
257 colorClearValue.alpha = alpha;
258}
259
260void Context::setClearDepth(float depth)
261{
262 depthClearValue = depth;
263}
264
265void Context::setClearStencil(int stencil)
266{
267 stencilClearValue = stencil;
268}
269
270// Returns an unused buffer name
271GLuint Context::createBuffer()
272{
273 unsigned int handle = 1;
274
275 while (mBufferMap.find(handle) != mBufferMap.end())
276 {
277 handle++;
278 }
279
280 mBufferMap[handle] = NULL;
281
282 return handle;
283}
284
285// Returns an unused shader/program name
286GLuint Context::createShader(GLenum type)
287{
288 unsigned int handle = 1;
289
290 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
291 {
292 handle++;
293 }
294
295 if (type == GL_VERTEX_SHADER)
296 {
297 mShaderMap[handle] = new VertexShader();
298 }
299 else if (type == GL_FRAGMENT_SHADER)
300 {
301 mShaderMap[handle] = new FragmentShader();
302 }
303 else UNREACHABLE();
304
305 return handle;
306}
307
308// Returns an unused program/shader name
309GLuint Context::createProgram()
310{
311 unsigned int handle = 1;
312
313 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
314 {
315 handle++;
316 }
317
318 mProgramMap[handle] = new Program();
319
320 return handle;
321}
322
323// Returns an unused texture name
324GLuint Context::createTexture()
325{
326 unsigned int handle = 1;
327
328 while (mTextureMap.find(handle) != mTextureMap.end())
329 {
330 handle++;
331 }
332
333 mTextureMap[handle] = NULL;
334
335 return handle;
336}
337
338// Returns an unused framebuffer name
339GLuint Context::createFramebuffer()
340{
341 unsigned int handle = 1;
342
343 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
344 {
345 handle++;
346 }
347
348 mFramebufferMap[handle] = NULL;
349
350 return handle;
351}
352
353// Returns an unused renderbuffer name
354GLuint Context::createRenderbuffer()
355{
356 unsigned int handle = 1;
357
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000358 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000359 {
360 handle++;
361 }
362
363 mRenderbufferMap[handle] = NULL;
364
365 return handle;
366}
367
368void Context::deleteBuffer(GLuint buffer)
369{
370 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
371
372 if (bufferObject != mBufferMap.end())
373 {
374 detachBuffer(buffer);
375
376 delete bufferObject->second;
377 mBufferMap.erase(bufferObject);
378 }
379}
380
381void Context::deleteShader(GLuint shader)
382{
383 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
384
385 if (shaderObject != mShaderMap.end())
386 {
387 if (!shaderObject->second->isAttached())
388 {
389 delete shaderObject->second;
390 mShaderMap.erase(shaderObject);
391 }
392 else
393 {
394 shaderObject->second->flagForDeletion();
395 }
396 }
397}
398
399void Context::deleteProgram(GLuint program)
400{
401 ProgramMap::iterator programObject = mProgramMap.find(program);
402
403 if (programObject != mProgramMap.end())
404 {
405 if (program != currentProgram)
406 {
407 delete programObject->second;
408 mProgramMap.erase(programObject);
409 }
410 else
411 {
412 programObject->second->flagForDeletion();
413 }
414 }
415}
416
417void Context::deleteTexture(GLuint texture)
418{
419 TextureMap::iterator textureObject = mTextureMap.find(texture);
420
421 if (textureObject != mTextureMap.end())
422 {
423 detachTexture(texture);
424
425 if (texture != 0)
426 {
427 delete textureObject->second;
428 }
429
430 mTextureMap.erase(textureObject);
431 }
432}
433
434void Context::deleteFramebuffer(GLuint framebuffer)
435{
436 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
437
438 if (framebufferObject != mFramebufferMap.end())
439 {
440 detachFramebuffer(framebuffer);
441
442 delete framebufferObject->second;
443 mFramebufferMap.erase(framebufferObject);
444 }
445}
446
447void Context::deleteRenderbuffer(GLuint renderbuffer)
448{
449 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
450
451 if (renderbufferObject != mRenderbufferMap.end())
452 {
453 detachRenderbuffer(renderbuffer);
454
455 delete renderbufferObject->second;
456 mRenderbufferMap.erase(renderbufferObject);
457 }
458}
459
460void Context::bindArrayBuffer(unsigned int buffer)
461{
462 if (buffer != 0 && !getBuffer(buffer))
463 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000464 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465 }
466
467 arrayBuffer = buffer;
468}
469
470void Context::bindElementArrayBuffer(unsigned int buffer)
471{
472 if (buffer != 0 && !getBuffer(buffer))
473 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000474 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000475 }
476
477 elementArrayBuffer = buffer;
478}
479
480void Context::bindTexture2D(GLuint texture)
481{
482 if (!getTexture(texture) || texture == 0)
483 {
484 if (texture != 0)
485 {
486 mTextureMap[texture] = new Texture2D();
487 }
488 else // Special case: 0 refers to different initial textures based on the target
489 {
490 mTextureMap[0] = mTexture2DZero;
491 }
492 }
493
494 texture2D = texture;
495
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000496 samplerTexture[SAMPLER_2D][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000497}
498
499void Context::bindTextureCubeMap(GLuint texture)
500{
501 if (!getTexture(texture) || texture == 0)
502 {
503 if (texture != 0)
504 {
505 mTextureMap[texture] = new TextureCubeMap();
506 }
507 else // Special case: 0 refers to different initial textures based on the target
508 {
509 mTextureMap[0] = mTextureCubeMapZero;
510 }
511 }
512
513 textureCubeMap = texture;
514
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000515 samplerTexture[SAMPLER_CUBE][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000516}
517
518void Context::bindFramebuffer(GLuint framebuffer)
519{
520 if (!getFramebuffer(framebuffer))
521 {
522 mFramebufferMap[framebuffer] = new Framebuffer();
523 }
524
525 this->framebuffer = framebuffer;
526}
527
528void Context::bindRenderbuffer(GLuint renderbuffer)
529{
530 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
531 {
532 mRenderbufferMap[renderbuffer] = new Renderbuffer();
533 }
534
535 this->renderbuffer = renderbuffer;
536}
537
538void Context::useProgram(GLuint program)
539{
540 Program *programObject = getCurrentProgram();
541
542 if (programObject && programObject->isFlaggedForDeletion())
543 {
544 deleteProgram(currentProgram);
545 }
546
547 currentProgram = program;
548}
549
550void Context::setFramebufferZero(Framebuffer *buffer)
551{
552 delete mFramebufferMap[0];
553 mFramebufferMap[0] = buffer;
554}
555
556void Context::setColorbufferZero(Colorbuffer *buffer)
557{
558 delete mColorbufferZero;
559 mColorbufferZero = buffer;
560}
561
562void Context::setDepthbufferZero(Depthbuffer *buffer)
563{
564 delete mDepthbufferZero;
565 mDepthbufferZero = buffer;
566}
567
568void Context::setStencilbufferZero(Stencilbuffer *buffer)
569{
570 delete mStencilbufferZero;
571 mStencilbufferZero = buffer;
572}
573
574void Context::setRenderbuffer(Renderbuffer *buffer)
575{
576 delete mRenderbufferMap[renderbuffer];
577 mRenderbufferMap[renderbuffer] = buffer;
578}
579
580Buffer *Context::getBuffer(unsigned int handle)
581{
582 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000583
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000584 if (buffer == mBufferMap.end())
585 {
586 return NULL;
587 }
588 else
589 {
590 return buffer->second;
591 }
592}
593
594Shader *Context::getShader(unsigned int handle)
595{
596 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000597
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598 if (shader == mShaderMap.end())
599 {
600 return NULL;
601 }
602 else
603 {
604 return shader->second;
605 }
606}
607
608Program *Context::getProgram(unsigned int handle)
609{
610 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000611
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000612 if (program == mProgramMap.end())
613 {
614 return NULL;
615 }
616 else
617 {
618 return program->second;
619 }
620}
621
622Texture *Context::getTexture(unsigned int handle)
623{
624 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000625
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626 if (texture == mTextureMap.end())
627 {
628 return NULL;
629 }
630 else
631 {
632 return texture->second;
633 }
634}
635
636Framebuffer *Context::getFramebuffer(unsigned int handle)
637{
638 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000639
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000640 if (framebuffer == mFramebufferMap.end())
641 {
642 return NULL;
643 }
644 else
645 {
646 return framebuffer->second;
647 }
648}
649
650Renderbuffer *Context::getRenderbuffer(unsigned int handle)
651{
652 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000653
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654 if (renderbuffer == mRenderbufferMap.end())
655 {
656 return NULL;
657 }
658 else
659 {
660 return renderbuffer->second;
661 }
662}
663
664Colorbuffer *Context::getColorbuffer(GLuint handle)
665{
666 if (handle != 0)
667 {
668 Renderbuffer *renderbuffer = getRenderbuffer(handle);
669
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000670 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000671 {
672 return static_cast<Colorbuffer*>(renderbuffer);
673 }
674 }
675 else // Special case: 0 refers to different initial render targets based on the attachment type
676 {
677 return mColorbufferZero;
678 }
679
680 return NULL;
681}
682
683Depthbuffer *Context::getDepthbuffer(GLuint handle)
684{
685 if (handle != 0)
686 {
687 Renderbuffer *renderbuffer = getRenderbuffer(handle);
688
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000689 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000690 {
691 return static_cast<Depthbuffer*>(renderbuffer);
692 }
693 }
694 else // Special case: 0 refers to different initial render targets based on the attachment type
695 {
696 return mDepthbufferZero;
697 }
698
699 return NULL;
700}
701
702Stencilbuffer *Context::getStencilbuffer(GLuint handle)
703{
704 if (handle != 0)
705 {
706 Renderbuffer *renderbuffer = getRenderbuffer(handle);
707
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000708 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000709 {
710 return static_cast<Stencilbuffer*>(renderbuffer);
711 }
712 }
713 else
714 {
715 return mStencilbufferZero;
716 }
717
718 return NULL;
719}
720
721Buffer *Context::getArrayBuffer()
722{
723 return getBuffer(arrayBuffer);
724}
725
726Buffer *Context::getElementArrayBuffer()
727{
728 return getBuffer(elementArrayBuffer);
729}
730
731Program *Context::getCurrentProgram()
732{
733 return getProgram(currentProgram);
734}
735
736Texture2D *Context::getTexture2D()
737{
738 if (texture2D == 0) // Special case: 0 refers to different initial textures based on the target
739 {
740 return mTexture2DZero;
741 }
742
743 return (Texture2D*)getTexture(texture2D);
744}
745
746TextureCubeMap *Context::getTextureCubeMap()
747{
748 if (textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
749 {
750 return mTextureCubeMapZero;
751 }
752
753 return (TextureCubeMap*)getTexture(textureCubeMap);
754}
755
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000756Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757{
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000758 return getTexture(samplerTexture[type][sampler]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000759}
760
761Framebuffer *Context::getFramebuffer()
762{
763 return getFramebuffer(framebuffer);
764}
765
766// Applies the render target surface, depth stencil surface, viewport rectangle and
767// scissor rectangle to the Direct3D 9 device
768bool Context::applyRenderTarget(bool ignoreViewport)
769{
770 IDirect3DDevice9 *device = getDevice();
771 Framebuffer *framebufferObject = getFramebuffer();
772
773 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
774 {
775 return false;
776 }
777
778 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
779 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
780
781 device->SetRenderTarget(0, renderTarget);
782 device->SetDepthStencilSurface(depthStencil);
783
784 D3DVIEWPORT9 viewport;
785 D3DSURFACE_DESC desc;
786 renderTarget->GetDesc(&desc);
787
788 if (ignoreViewport)
789 {
790 viewport.X = 0;
791 viewport.Y = 0;
792 viewport.Width = desc.Width;
793 viewport.Height = desc.Height;
794 viewport.MinZ = 0.0f;
795 viewport.MaxZ = 1.0f;
796 }
797 else
798 {
daniel@transgaming.com16973022010-03-11 19:22:19 +0000799 viewport.X = std::max(viewportX, 0);
800 viewport.Y = std::max(viewportY, 0);
801 viewport.Width = std::min(viewportWidth, (int)desc.Width - (int)viewport.X);
802 viewport.Height = std::min(viewportHeight, (int)desc.Height - (int)viewport.Y);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000803 viewport.MinZ = clamp01(zNear);
804 viewport.MaxZ = clamp01(zFar);
805 }
806
807 device->SetViewport(&viewport);
808
809 if (scissorTest)
810 {
811 RECT rect = {scissorX,
812 scissorY,
813 scissorX + scissorWidth,
814 scissorY + scissorHeight};
815
816 device->SetScissorRect(&rect);
817 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
818 }
819 else
820 {
821 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
822 }
823
824 if (currentProgram)
825 {
826 D3DSURFACE_DESC description;
827 renderTarget->GetDesc(&description);
828 Program *programObject = getCurrentProgram();
829
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000830 GLint halfPixelSize = programObject->getUniformLocation("gl_HalfPixelSize");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831 GLfloat xy[2] = {1.0f / description.Width, 1.0f / description.Height};
832 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000833
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000834 GLint window = programObject->getUniformLocation("gl_Window");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000835 GLfloat whxy[4] = {viewportWidth / 2.0f, viewportHeight / 2.0f, (float)viewportX + viewportWidth / 2.0f, (float)viewportY + viewportHeight / 2.0f};
836 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
837
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000838 GLint depth = programObject->getUniformLocation("gl_Depth");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000839 GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
840 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
841
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000842 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000843 programObject->setUniform1fv(near, 1, &zNear);
844
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000845 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000846 programObject->setUniform1fv(far, 1, &zFar);
847
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000848 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000849 GLfloat zDiff = zFar - zNear;
850 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000851 }
852
853 return true;
854}
855
856// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
857void Context::applyState()
858{
859 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000860 Program *programObject = getCurrentProgram();
861
862 GLint frontCCW = programObject->getUniformLocation("__frontCCW");
863 GLint ccw = (frontFace == GL_CCW);
864 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000865
866 if (cullFace)
867 {
868 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(cullMode, frontFace));
869 }
870 else
871 {
872 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
873 }
874
875 if (depthTest)
876 {
877 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
878 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(depthFunc));
879 }
880 else
881 {
882 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
883 }
884
885 if (blend)
886 {
887 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
888
889 if (sourceBlendRGB != GL_CONSTANT_ALPHA && sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
890 destBlendRGB != GL_CONSTANT_ALPHA && destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
891 {
892 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(blendColor));
893 }
894 else
895 {
896 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(blendColor.alpha),
897 unorm<8>(blendColor.alpha),
898 unorm<8>(blendColor.alpha),
899 unorm<8>(blendColor.alpha)));
900 }
901
902 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(sourceBlendRGB));
903 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(destBlendRGB));
904 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(blendEquationRGB));
905
906 if (sourceBlendRGB != sourceBlendAlpha || destBlendRGB != destBlendAlpha || blendEquationRGB != blendEquationAlpha)
907 {
908 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
909
910 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(sourceBlendAlpha));
911 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(destBlendAlpha));
912 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(blendEquationAlpha));
913
914 }
915 else
916 {
917 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
918 }
919 }
920 else
921 {
922 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
923 }
924
925 if (stencilTest)
926 {
927 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
928 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
929
930 // FIXME: Unsupported by D3D9
931 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
932 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
933 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com1436e262010-03-17 03:58:56 +0000934 if(stencilWritemask != stencilBackWritemask || stencilRef != stencilBackRef || stencilMask != stencilBackMask)
935 {
936 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
937 return error(GL_INVALID_OPERATION);
938 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000939
940 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWritemask);
941 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilFunc));
942
943 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilRef); // FIXME: Clamp to range
944 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
945
946 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilFail));
947 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilPassDepthFail));
948 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilPassDepthPass));
949
950 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWritemask);
951 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilBackFunc));
952
953 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilBackRef); // FIXME: Clamp to range
954 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilBackMask);
955
956 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilBackFail));
957 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilBackPassDepthFail));
958 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilBackPassDepthPass));
959 }
960 else
961 {
962 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
963 }
964
965 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha));
966 device->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
967
968 if (polygonOffsetFill)
969 {
970 UNIMPLEMENTED(); // FIXME
971 }
972
973 if (sampleAlphaToCoverage)
974 {
975 UNIMPLEMENTED(); // FIXME
976 }
977
978 if (sampleCoverage)
979 {
980 UNIMPLEMENTED(); // FIXME: Ignore when SAMPLE_BUFFERS is not one
981 }
982
983 device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
984}
985
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000986// Fill in the programAttribute field of the array of TranslatedAttributes based on the active GLSL program.
987void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000988{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000989 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000991 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000992 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000993 attributes[i].programAttribute = getCurrentProgram()->getInputMapping(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000994 }
995 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000996}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000997
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000998// The indices parameter to glDrawElements can have two interpretations:
999// - as a pointer into client memory
1000// - as an offset into the current GL_ELEMENT_ARRAY_BUFFER buffer
1001// Handle these cases here and return a pointer to the index data.
1002const Index *Context::adjustIndexPointer(const void *indices)
1003{
1004 if (elementArrayBuffer)
1005 {
1006 Buffer *buffer = getBuffer(elementArrayBuffer);
1007 return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
1008 }
1009 else
1010 {
1011 return static_cast<const Index*>(indices);
1012 }
1013}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001014
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001015void Context::applyVertexBuffer(GLint first, GLsizei count)
1016{
1017 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1018
1019 mVertexDataManager->preRenderValidate(first, count, translated);
1020
1021 lookupAttributeMapping(translated);
1022
1023 mBufferBackEnd->preDraw(translated);
1024}
1025
1026void Context::applyVertexBuffer(GLsizei count, const void *indices, GLenum indexType)
1027{
1028 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1029
1030 mVertexDataManager->preRenderValidate(adjustIndexPointer(indices), count, translated);
1031
1032 lookupAttributeMapping(translated);
1033
1034 mBufferBackEnd->preDraw(translated);
1035}
1036
1037// Applies the indices and element array bindings to the Direct3D 9 device
1038void Context::applyIndexBuffer(const void *indices, GLsizei count)
1039{
1040 GLsizei length = count * sizeof(Index);
1041
1042 IDirect3DDevice9 *device = getDevice();
1043
1044 IDirect3DIndexBuffer9 *indexBuffer = NULL;
1045 void *data;
1046
1047 HRESULT result = device->CreateIndexBuffer(length, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexBuffer, NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001048
1049 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1050 {
1051 return error(GL_OUT_OF_MEMORY);
1052 }
1053
1054 ASSERT(SUCCEEDED(result));
1055
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001056 if (indexBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001057 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001058 indexBuffer->Lock(0, length, &data, 0);
1059 memcpy(data, adjustIndexPointer(indices), length);
1060 indexBuffer->Unlock();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001061
1062 device->SetIndices(indexBuffer);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001063 indexBuffer->Release(); // Will only effectively be deleted when no longer in use
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001064 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001065
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001066 startIndex = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001067}
1068
1069// Applies the shaders and shader constants to the Direct3D 9 device
1070void Context::applyShaders()
1071{
1072 IDirect3DDevice9 *device = getDevice();
1073 Program *programObject = getCurrentProgram();
1074 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1075 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1076
1077 device->SetVertexShader(vertexShader);
1078 device->SetPixelShader(pixelShader);
1079
1080 programObject->applyUniforms();
1081}
1082
1083// Applies the textures and sampler states to the Direct3D 9 device
1084void Context::applyTextures()
1085{
1086 IDirect3DDevice9 *device = getDevice();
1087 Program *programObject = getCurrentProgram();
1088
1089 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1090 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001091 int textureUnit = programObject->getSamplerMapping(sampler);
1092 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001093 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001094 SamplerType textureType = programObject->getSamplerType(sampler);
1095
1096 Texture *texture = getSamplerTexture(textureUnit, textureType);
1097
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001098 if (texture->isComplete())
1099 {
1100 GLenum wrapS = texture->getWrapS();
1101 GLenum wrapT = texture->getWrapT();
1102 GLenum minFilter = texture->getMinFilter();
1103 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001104
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001105 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1106 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001107
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001108 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1109 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1110 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1111 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1112 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001113
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001114 device->SetTexture(sampler, texture->getTexture());
1115 }
1116 else
1117 {
1118 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1119 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001120 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001121 else
1122 {
1123 device->SetTexture(sampler, NULL);
1124 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001125 }
1126}
1127
1128void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1129{
1130 Framebuffer *framebuffer = getFramebuffer();
1131 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1132 IDirect3DDevice9 *device = getDevice();
1133
1134 D3DSURFACE_DESC desc;
1135 renderTarget->GetDesc(&desc);
1136
1137 IDirect3DSurface9 *systemSurface;
1138 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1139
1140 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1141 {
1142 return error(GL_OUT_OF_MEMORY);
1143 }
1144
1145 ASSERT(SUCCEEDED(result));
1146
1147 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1148 {
1149 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1150 }
1151
1152 result = device->GetRenderTargetData(renderTarget, systemSurface);
1153
1154 if (result == D3DERR_DRIVERINTERNALERROR)
1155 {
1156 systemSurface->Release();
1157
1158 return error(GL_OUT_OF_MEMORY);
1159 }
1160
1161 if (FAILED(result))
1162 {
1163 UNREACHABLE();
1164 systemSurface->Release();
1165
1166 return; // No sensible error to generate
1167 }
1168
1169 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001170 RECT rect = {std::max(x, 0),
1171 std::max(y, 0),
1172 std::min(x + width, (int)desc.Width),
1173 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001174
1175 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1176
1177 if (FAILED(result))
1178 {
1179 UNREACHABLE();
1180 systemSurface->Release();
1181
1182 return; // No sensible error to generate
1183 }
1184
1185 unsigned char *source = (unsigned char*)lock.pBits;
1186 unsigned char *dest = (unsigned char*)pixels;
1187
1188 for (int j = 0; j < rect.bottom - rect.top; j++)
1189 {
1190 for (int i = 0; i < rect.right - rect.left; i++)
1191 {
1192 float r;
1193 float g;
1194 float b;
1195 float a;
1196
1197 switch (desc.Format)
1198 {
1199 case D3DFMT_R5G6B5:
1200 {
1201 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1202
1203 a = 1.0f;
1204 b = (rgb & 0x001F) * (1.0f / 0x001F);
1205 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1206 r = (rgb & 0xF800) * (1.0f / 0xF800);
1207 }
1208 break;
1209 case D3DFMT_X1R5G5B5:
1210 {
1211 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1212
1213 a = 1.0f;
1214 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1215 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1216 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1217 }
1218 break;
1219 case D3DFMT_A1R5G5B5:
1220 {
1221 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1222
1223 a = (argb & 0x8000) ? 1.0f : 0.0f;
1224 b = (argb & 0x001F) * (1.0f / 0x001F);
1225 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1226 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1227 }
1228 break;
1229 case D3DFMT_A8R8G8B8:
1230 {
1231 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1232
1233 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1234 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1235 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1236 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1237 }
1238 break;
1239 case D3DFMT_X8R8G8B8:
1240 {
1241 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1242
1243 a = 1.0f;
1244 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1245 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1246 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1247 }
1248 break;
1249 case D3DFMT_A2R10G10B10:
1250 {
1251 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1252
1253 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1254 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1255 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1256 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1257 }
1258 break;
1259 default:
1260 UNIMPLEMENTED(); // FIXME
1261 UNREACHABLE();
1262 }
1263
1264 switch (format)
1265 {
1266 case GL_RGBA:
1267 switch (type)
1268 {
1269 case GL_UNSIGNED_BYTE:
1270 dest[4 * (i + j * width) + 0] = (unsigned char)(255 * r + 0.5f);
1271 dest[4 * (i + j * width) + 1] = (unsigned char)(255 * g + 0.5f);
1272 dest[4 * (i + j * width) + 2] = (unsigned char)(255 * b + 0.5f);
1273 dest[4 * (i + j * width) + 3] = (unsigned char)(255 * a + 0.5f);
1274 break;
1275 default: UNREACHABLE();
1276 }
1277 break;
1278 case IMPLEMENTATION_COLOR_READ_FORMAT:
1279 switch (type)
1280 {
1281 case IMPLEMENTATION_COLOR_READ_TYPE:
1282 break;
1283 default: UNREACHABLE();
1284 }
1285 break;
1286 default: UNREACHABLE();
1287 }
1288 }
1289 }
1290
1291 systemSurface->UnlockRect();
1292
1293 systemSurface->Release();
1294}
1295
1296void Context::clear(GLbitfield mask)
1297{
1298 IDirect3DDevice9 *device = getDevice();
1299 DWORD flags = 0;
1300
1301 if (mask & GL_COLOR_BUFFER_BIT)
1302 {
1303 mask &= ~GL_COLOR_BUFFER_BIT;
1304 flags |= D3DCLEAR_TARGET;
1305 }
1306
1307 if (mask & GL_DEPTH_BUFFER_BIT)
1308 {
1309 mask &= ~GL_DEPTH_BUFFER_BIT;
1310 if (depthMask)
1311 {
1312 flags |= D3DCLEAR_ZBUFFER;
1313 }
1314 }
1315
1316 Framebuffer *framebufferObject = getFramebuffer();
1317 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1318
1319 GLuint stencilUnmasked = 0x0;
1320
1321 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
1322 {
1323 D3DSURFACE_DESC desc;
1324 depthStencil->GetDesc(&desc);
1325
1326 mask &= ~GL_STENCIL_BUFFER_BIT;
1327 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
1328 stencilUnmasked = (0x1 << stencilSize) - 1;
1329
1330 if (stencilUnmasked != 0x0)
1331 {
1332 flags |= D3DCLEAR_STENCIL;
1333 }
1334 }
1335
1336 if (mask != 0)
1337 {
1338 return error(GL_INVALID_VALUE);
1339 }
1340
1341 applyRenderTarget(true); // Clips the clear to the scissor rectangle but not the viewport
1342
1343 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(colorClearValue.alpha), unorm<8>(colorClearValue.red), unorm<8>(colorClearValue.green), unorm<8>(colorClearValue.blue));
1344 float depth = clamp01(depthClearValue);
1345 int stencil = stencilClearValue & 0x000000FF;
1346
1347 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1348
1349 D3DSURFACE_DESC desc;
1350 renderTarget->GetDesc(&desc);
1351
1352 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || colorMaskAlpha;
1353
1354 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
1355 (stencilWritemask & stencilUnmasked) != stencilUnmasked;
1356 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001357 !(colorMaskRed && colorMaskGreen &&
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001358 colorMaskBlue && alphaUnmasked);
1359
1360 if (needMaskedColorClear || needMaskedStencilClear)
1361 {
1362 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1363 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1364 device->SetRenderState(D3DRS_ZENABLE, FALSE);
1365 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1366 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1367 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1368 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1369 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1370
1371 if (flags & D3DCLEAR_TARGET)
1372 {
1373 device->SetRenderState(D3DRS_COLORWRITEENABLE, (colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
1374 (colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
1375 (colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
1376 (colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
1377 }
1378 else
1379 {
1380 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1381 }
1382
1383 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
1384 {
1385 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1386 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
1387 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
1388 device->SetRenderState(D3DRS_STENCILREF, stencil);
1389 device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001390 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001391 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
1392 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
1393 }
1394 else
1395 {
1396 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1397 }
1398
1399 device->SetPixelShader(NULL);
1400 device->SetVertexShader(NULL);
1401 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1402
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001403 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001404 {
1405 float x, y, z, w;
1406 D3DCOLOR diffuse;
1407 };
1408
1409 Vertex quad[4];
1410 quad[0].x = 0.0f;
1411 quad[0].y = (float)desc.Height;
1412 quad[0].z = 0.0f;
1413 quad[0].w = 1.0f;
1414 quad[0].diffuse = color;
1415
1416 quad[1].x = (float)desc.Width;
1417 quad[1].y = (float)desc.Height;
1418 quad[1].z = 0.0f;
1419 quad[1].w = 1.0f;
1420 quad[1].diffuse = color;
1421
1422 quad[2].x = 0.0f;
1423 quad[2].y = 0.0f;
1424 quad[2].z = 0.0f;
1425 quad[2].w = 1.0f;
1426 quad[2].diffuse = color;
1427
1428 quad[3].x = (float)desc.Width;
1429 quad[3].y = 0.0f;
1430 quad[3].z = 0.0f;
1431 quad[3].w = 1.0f;
1432 quad[3].diffuse = color;
1433
1434 device->BeginScene();
1435 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
1436 device->EndScene();
1437
1438 if (flags & D3DCLEAR_ZBUFFER)
1439 {
1440 device->SetRenderState(D3DRS_ZENABLE, TRUE);
1441 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1442 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
1443 }
1444 }
1445 else
1446 {
1447 device->Clear(0, NULL, flags, color, depth, stencil);
1448 }
1449}
1450
1451void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
1452{
1453 if (!currentProgram)
1454 {
1455 return error(GL_INVALID_OPERATION);
1456 }
1457
1458 IDirect3DDevice9 *device = getDevice();
1459 D3DPRIMITIVETYPE primitiveType;
1460 int primitiveCount;
1461
1462 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1463 return error(GL_INVALID_ENUM);
1464
1465 if (primitiveCount <= 0)
1466 {
1467 return;
1468 }
1469
1470 if (!applyRenderTarget(false))
1471 {
1472 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1473 }
1474
1475 applyState();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001476 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001477 applyShaders();
1478 applyTextures();
1479
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001480 if (!cullSkipsDraw(mode))
1481 {
1482 device->BeginScene();
1483 device->DrawPrimitive(primitiveType, first, primitiveCount);
1484 device->EndScene();
1485 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001486}
1487
1488void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
1489{
1490 if (!currentProgram)
1491 {
1492 return error(GL_INVALID_OPERATION);
1493 }
1494
1495 if (!indices && !elementArrayBuffer)
1496 {
1497 return error(GL_INVALID_OPERATION);
1498 }
1499
1500 IDirect3DDevice9 *device = getDevice();
1501 D3DPRIMITIVETYPE primitiveType;
1502 int primitiveCount;
1503
1504 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1505 return error(GL_INVALID_ENUM);
1506
1507 if (primitiveCount <= 0)
1508 {
1509 return;
1510 }
1511
1512 if (!applyRenderTarget(false))
1513 {
1514 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1515 }
1516
1517 applyState();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001518 applyVertexBuffer(count, indices, type);
1519 applyIndexBuffer(indices, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001520 applyShaders();
1521 applyTextures();
1522
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001523 if (!cullSkipsDraw(mode))
1524 {
1525 device->BeginScene();
1526 device->DrawIndexedPrimitive(primitiveType, 0, 0, count, startIndex, primitiveCount);
1527 device->EndScene();
1528 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001529}
1530
1531void Context::finish()
1532{
1533 IDirect3DDevice9 *device = getDevice();
1534 IDirect3DQuery9 *occlusionQuery = NULL;
1535
1536 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
1537
1538 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1539 {
1540 return error(GL_OUT_OF_MEMORY);
1541 }
1542
1543 ASSERT(SUCCEEDED(result));
1544
1545 if (occlusionQuery)
1546 {
1547 occlusionQuery->Issue(D3DISSUE_BEGIN);
1548
1549 // Render something outside the render target
1550 device->SetPixelShader(NULL);
1551 device->SetVertexShader(NULL);
1552 device->SetFVF(D3DFVF_XYZRHW);
1553 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
1554 device->BeginScene();
1555 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
1556 device->EndScene();
1557
1558 occlusionQuery->Issue(D3DISSUE_END);
1559
1560 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1561 {
1562 // Keep polling, but allow other threads to do something useful first
1563 Sleep(0);
1564 }
1565
1566 occlusionQuery->Release();
1567 }
1568}
1569
1570void Context::flush()
1571{
1572 IDirect3DDevice9 *device = getDevice();
1573 IDirect3DQuery9 *eventQuery = NULL;
1574
1575 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
1576
1577 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1578 {
1579 return error(GL_OUT_OF_MEMORY);
1580 }
1581
1582 ASSERT(SUCCEEDED(result));
1583
1584 if (eventQuery)
1585 {
1586 eventQuery->Issue(D3DISSUE_END);
1587
1588 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1589 {
1590 // Keep polling, but allow other threads to do something useful first
1591 Sleep(0);
1592 }
1593
1594 eventQuery->Release();
1595 }
1596}
1597
1598void Context::recordInvalidEnum()
1599{
1600 mInvalidEnum = true;
1601}
1602
1603void Context::recordInvalidValue()
1604{
1605 mInvalidValue = true;
1606}
1607
1608void Context::recordInvalidOperation()
1609{
1610 mInvalidOperation = true;
1611}
1612
1613void Context::recordOutOfMemory()
1614{
1615 mOutOfMemory = true;
1616}
1617
1618void Context::recordInvalidFramebufferOperation()
1619{
1620 mInvalidFramebufferOperation = true;
1621}
1622
1623// Get one of the recorded errors and clear its flag, if any.
1624// [OpenGL ES 2.0.24] section 2.5 page 13.
1625GLenum Context::getError()
1626{
1627 if (mInvalidEnum)
1628 {
1629 mInvalidEnum = false;
1630
1631 return GL_INVALID_ENUM;
1632 }
1633
1634 if (mInvalidValue)
1635 {
1636 mInvalidValue = false;
1637
1638 return GL_INVALID_VALUE;
1639 }
1640
1641 if (mInvalidOperation)
1642 {
1643 mInvalidOperation = false;
1644
1645 return GL_INVALID_OPERATION;
1646 }
1647
1648 if (mOutOfMemory)
1649 {
1650 mOutOfMemory = false;
1651
1652 return GL_OUT_OF_MEMORY;
1653 }
1654
1655 if (mInvalidFramebufferOperation)
1656 {
1657 mInvalidFramebufferOperation = false;
1658
1659 return GL_INVALID_FRAMEBUFFER_OPERATION;
1660 }
1661
1662 return GL_NO_ERROR;
1663}
1664
1665void Context::detachBuffer(GLuint buffer)
1666{
1667 // [OpenGL ES 2.0.24] section 2.9 page 22:
1668 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
1669 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
1670
1671 if (arrayBuffer == buffer)
1672 {
1673 arrayBuffer = 0;
1674 }
1675
1676 if (elementArrayBuffer == buffer)
1677 {
1678 elementArrayBuffer = 0;
1679 }
1680
1681 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
1682 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001683 if (vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001684 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001685 vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001686 }
1687 }
1688}
1689
1690void Context::detachTexture(GLuint texture)
1691{
1692 // [OpenGL ES 2.0.24] section 3.8 page 84:
1693 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
1694 // rebound to texture object zero
1695
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001696 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001697 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001698 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001699 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001700 if (samplerTexture[type][sampler] == texture)
1701 {
1702 samplerTexture[type][sampler] = 0;
1703 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001704 }
1705 }
1706
1707 // [OpenGL ES 2.0.24] section 4.4 page 112:
1708 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
1709 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
1710 // image was attached in the currently bound framebuffer.
1711
1712 Framebuffer *framebuffer = getFramebuffer();
1713
1714 if (framebuffer)
1715 {
1716 framebuffer->detachTexture(texture);
1717 }
1718}
1719
1720void Context::detachFramebuffer(GLuint framebuffer)
1721{
1722 // [OpenGL ES 2.0.24] section 4.4 page 107:
1723 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
1724 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
1725
1726 if (this->framebuffer == framebuffer)
1727 {
1728 bindFramebuffer(0);
1729 }
1730}
1731
1732void Context::detachRenderbuffer(GLuint renderbuffer)
1733{
1734 // [OpenGL ES 2.0.24] section 4.4 page 109:
1735 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
1736 // had been executed with the target RENDERBUFFER and name of zero.
1737
1738 if (this->renderbuffer == renderbuffer)
1739 {
1740 bindRenderbuffer(0);
1741 }
1742
1743 // [OpenGL ES 2.0.24] section 4.4 page 111:
1744 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
1745 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
1746 // point to which this image was attached in the currently bound framebuffer.
1747
1748 Framebuffer *framebuffer = getFramebuffer();
1749
1750 if (framebuffer)
1751 {
1752 framebuffer->detachRenderbuffer(renderbuffer);
1753 }
1754}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001755
1756Texture *Context::getIncompleteTexture(SamplerType type)
1757{
1758 Texture *t = mIncompleteTextures[type];
1759
1760 if (t == NULL)
1761 {
1762 static const GLubyte color[] = { 0, 0, 0, 255 };
1763
1764 switch (type)
1765 {
1766 default:
1767 UNREACHABLE();
1768 // default falls through to SAMPLER_2D
1769
1770 case SAMPLER_2D:
1771 {
1772 Texture2D *incomplete2d = new Texture2D;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001773 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001774 t = incomplete2d;
1775 }
1776 break;
1777
1778 case SAMPLER_CUBE:
1779 {
1780 TextureCubeMap *incompleteCube = new TextureCubeMap;
1781
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001782 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1783 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1784 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1785 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1786 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1787 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001788
1789 t = incompleteCube;
1790 }
1791 break;
1792 }
1793
1794 mIncompleteTextures[type] = t;
1795 }
1796
1797 return t;
1798}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001799
1800bool Context::cullSkipsDraw(GLenum primitiveType)
1801{
1802 if (cullFace && cullMode == GL_FRONT_AND_BACK &&
1803 (primitiveType == GL_TRIANGLES || primitiveType == GL_TRIANGLE_FAN || primitiveType == GL_TRIANGLE_STRIP))
1804 {
1805 return true;
1806 }
1807 else
1808 {
1809 return false;
1810 }
1811}
1812
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001813}
1814
1815extern "C"
1816{
1817gl::Context *glCreateContext(const egl::Config *config)
1818{
1819 return new gl::Context(config);
1820}
1821
1822void glDestroyContext(gl::Context *context)
1823{
1824 delete context;
1825
1826 if (context == gl::getContext())
1827 {
1828 gl::makeCurrent(NULL, NULL, NULL);
1829 }
1830}
1831
1832void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
1833{
1834 gl::makeCurrent(context, display, surface);
1835}
1836
1837gl::Context *glGetCurrentContext()
1838{
1839 return gl::getContext();
1840}
1841}