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