blob: c2b0614ca79eed3d571ac027021f183ab2197041 [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"
15#include "Display.h"
16#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;
145}
146
147Context::~Context()
148{
149 currentProgram = 0;
150
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000151 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
152 {
153 delete mIncompleteTextures[type];
154 }
155
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156 delete mTexture2DZero;
157 delete mTextureCubeMapZero;
158
159 delete mColorbufferZero;
160 delete mDepthbufferZero;
161 delete mStencilbufferZero;
162
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000163 delete mBufferBackEnd;
164 delete mVertexDataManager;
165
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166 while (!mBufferMap.empty())
167 {
168 deleteBuffer(mBufferMap.begin()->first);
169 }
170
171 while (!mProgramMap.empty())
172 {
173 deleteProgram(mProgramMap.begin()->first);
174 }
175
176 while (!mShaderMap.empty())
177 {
178 deleteShader(mShaderMap.begin()->first);
179 }
180
181 while (!mFramebufferMap.empty())
182 {
183 deleteFramebuffer(mFramebufferMap.begin()->first);
184 }
185
186 while (!mRenderbufferMap.empty())
187 {
188 deleteRenderbuffer(mRenderbufferMap.begin()->first);
189 }
190
191 while (!mTextureMap.empty())
192 {
193 deleteTexture(mTextureMap.begin()->first);
194 }
195}
196
197void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
198{
199 IDirect3DDevice9 *device = display->getDevice();
200
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000201 if (!mBufferBackEnd)
202 {
203 mBufferBackEnd = new Dx9BackEnd(device);
204 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
205 }
206
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
208 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000209 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210
211 Framebuffer *framebufferZero = new Framebuffer();
212 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000213 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
214 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215
216 setFramebufferZero(framebufferZero);
217 setColorbufferZero(colorbufferZero);
218 setDepthbufferZero(depthbufferZero);
219 setStencilbufferZero(stencilbufferZero);
220
221 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
222 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
223 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
224
225 defaultRenderTarget->Release();
226
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000227 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000229 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230 }
231}
232
233void Context::setClearColor(float red, float green, float blue, float alpha)
234{
235 colorClearValue.red = red;
236 colorClearValue.green = green;
237 colorClearValue.blue = blue;
238 colorClearValue.alpha = alpha;
239}
240
241void Context::setClearDepth(float depth)
242{
243 depthClearValue = depth;
244}
245
246void Context::setClearStencil(int stencil)
247{
248 stencilClearValue = stencil;
249}
250
251// Returns an unused buffer name
252GLuint Context::createBuffer()
253{
254 unsigned int handle = 1;
255
256 while (mBufferMap.find(handle) != mBufferMap.end())
257 {
258 handle++;
259 }
260
261 mBufferMap[handle] = NULL;
262
263 return handle;
264}
265
266// Returns an unused shader/program name
267GLuint Context::createShader(GLenum type)
268{
269 unsigned int handle = 1;
270
271 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
272 {
273 handle++;
274 }
275
276 if (type == GL_VERTEX_SHADER)
277 {
278 mShaderMap[handle] = new VertexShader();
279 }
280 else if (type == GL_FRAGMENT_SHADER)
281 {
282 mShaderMap[handle] = new FragmentShader();
283 }
284 else UNREACHABLE();
285
286 return handle;
287}
288
289// Returns an unused program/shader name
290GLuint Context::createProgram()
291{
292 unsigned int handle = 1;
293
294 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
295 {
296 handle++;
297 }
298
299 mProgramMap[handle] = new Program();
300
301 return handle;
302}
303
304// Returns an unused texture name
305GLuint Context::createTexture()
306{
307 unsigned int handle = 1;
308
309 while (mTextureMap.find(handle) != mTextureMap.end())
310 {
311 handle++;
312 }
313
314 mTextureMap[handle] = NULL;
315
316 return handle;
317}
318
319// Returns an unused framebuffer name
320GLuint Context::createFramebuffer()
321{
322 unsigned int handle = 1;
323
324 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
325 {
326 handle++;
327 }
328
329 mFramebufferMap[handle] = NULL;
330
331 return handle;
332}
333
334// Returns an unused renderbuffer name
335GLuint Context::createRenderbuffer()
336{
337 unsigned int handle = 1;
338
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000339 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000340 {
341 handle++;
342 }
343
344 mRenderbufferMap[handle] = NULL;
345
346 return handle;
347}
348
349void Context::deleteBuffer(GLuint buffer)
350{
351 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
352
353 if (bufferObject != mBufferMap.end())
354 {
355 detachBuffer(buffer);
356
357 delete bufferObject->second;
358 mBufferMap.erase(bufferObject);
359 }
360}
361
362void Context::deleteShader(GLuint shader)
363{
364 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
365
366 if (shaderObject != mShaderMap.end())
367 {
368 if (!shaderObject->second->isAttached())
369 {
370 delete shaderObject->second;
371 mShaderMap.erase(shaderObject);
372 }
373 else
374 {
375 shaderObject->second->flagForDeletion();
376 }
377 }
378}
379
380void Context::deleteProgram(GLuint program)
381{
382 ProgramMap::iterator programObject = mProgramMap.find(program);
383
384 if (programObject != mProgramMap.end())
385 {
386 if (program != currentProgram)
387 {
388 delete programObject->second;
389 mProgramMap.erase(programObject);
390 }
391 else
392 {
393 programObject->second->flagForDeletion();
394 }
395 }
396}
397
398void Context::deleteTexture(GLuint texture)
399{
400 TextureMap::iterator textureObject = mTextureMap.find(texture);
401
402 if (textureObject != mTextureMap.end())
403 {
404 detachTexture(texture);
405
406 if (texture != 0)
407 {
408 delete textureObject->second;
409 }
410
411 mTextureMap.erase(textureObject);
412 }
413}
414
415void Context::deleteFramebuffer(GLuint framebuffer)
416{
417 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
418
419 if (framebufferObject != mFramebufferMap.end())
420 {
421 detachFramebuffer(framebuffer);
422
423 delete framebufferObject->second;
424 mFramebufferMap.erase(framebufferObject);
425 }
426}
427
428void Context::deleteRenderbuffer(GLuint renderbuffer)
429{
430 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
431
432 if (renderbufferObject != mRenderbufferMap.end())
433 {
434 detachRenderbuffer(renderbuffer);
435
436 delete renderbufferObject->second;
437 mRenderbufferMap.erase(renderbufferObject);
438 }
439}
440
441void Context::bindArrayBuffer(unsigned int buffer)
442{
443 if (buffer != 0 && !getBuffer(buffer))
444 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000445 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446 }
447
448 arrayBuffer = buffer;
449}
450
451void Context::bindElementArrayBuffer(unsigned int buffer)
452{
453 if (buffer != 0 && !getBuffer(buffer))
454 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000455 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000456 }
457
458 elementArrayBuffer = buffer;
459}
460
461void Context::bindTexture2D(GLuint texture)
462{
463 if (!getTexture(texture) || texture == 0)
464 {
465 if (texture != 0)
466 {
467 mTextureMap[texture] = new Texture2D();
468 }
469 else // Special case: 0 refers to different initial textures based on the target
470 {
471 mTextureMap[0] = mTexture2DZero;
472 }
473 }
474
475 texture2D = texture;
476
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000477 samplerTexture[SAMPLER_2D][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478}
479
480void Context::bindTextureCubeMap(GLuint texture)
481{
482 if (!getTexture(texture) || texture == 0)
483 {
484 if (texture != 0)
485 {
486 mTextureMap[texture] = new TextureCubeMap();
487 }
488 else // Special case: 0 refers to different initial textures based on the target
489 {
490 mTextureMap[0] = mTextureCubeMapZero;
491 }
492 }
493
494 textureCubeMap = texture;
495
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000496 samplerTexture[SAMPLER_CUBE][activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000497}
498
499void Context::bindFramebuffer(GLuint framebuffer)
500{
501 if (!getFramebuffer(framebuffer))
502 {
503 mFramebufferMap[framebuffer] = new Framebuffer();
504 }
505
506 this->framebuffer = framebuffer;
507}
508
509void Context::bindRenderbuffer(GLuint renderbuffer)
510{
511 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
512 {
513 mRenderbufferMap[renderbuffer] = new Renderbuffer();
514 }
515
516 this->renderbuffer = renderbuffer;
517}
518
519void Context::useProgram(GLuint program)
520{
521 Program *programObject = getCurrentProgram();
522
523 if (programObject && programObject->isFlaggedForDeletion())
524 {
525 deleteProgram(currentProgram);
526 }
527
528 currentProgram = program;
529}
530
531void Context::setFramebufferZero(Framebuffer *buffer)
532{
533 delete mFramebufferMap[0];
534 mFramebufferMap[0] = buffer;
535}
536
537void Context::setColorbufferZero(Colorbuffer *buffer)
538{
539 delete mColorbufferZero;
540 mColorbufferZero = buffer;
541}
542
543void Context::setDepthbufferZero(Depthbuffer *buffer)
544{
545 delete mDepthbufferZero;
546 mDepthbufferZero = buffer;
547}
548
549void Context::setStencilbufferZero(Stencilbuffer *buffer)
550{
551 delete mStencilbufferZero;
552 mStencilbufferZero = buffer;
553}
554
555void Context::setRenderbuffer(Renderbuffer *buffer)
556{
557 delete mRenderbufferMap[renderbuffer];
558 mRenderbufferMap[renderbuffer] = buffer;
559}
560
561Buffer *Context::getBuffer(unsigned int handle)
562{
563 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000564
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000565 if (buffer == mBufferMap.end())
566 {
567 return NULL;
568 }
569 else
570 {
571 return buffer->second;
572 }
573}
574
575Shader *Context::getShader(unsigned int handle)
576{
577 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000578
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000579 if (shader == mShaderMap.end())
580 {
581 return NULL;
582 }
583 else
584 {
585 return shader->second;
586 }
587}
588
589Program *Context::getProgram(unsigned int handle)
590{
591 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000592
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593 if (program == mProgramMap.end())
594 {
595 return NULL;
596 }
597 else
598 {
599 return program->second;
600 }
601}
602
603Texture *Context::getTexture(unsigned int handle)
604{
605 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000606
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000607 if (texture == mTextureMap.end())
608 {
609 return NULL;
610 }
611 else
612 {
613 return texture->second;
614 }
615}
616
617Framebuffer *Context::getFramebuffer(unsigned int handle)
618{
619 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000620
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000621 if (framebuffer == mFramebufferMap.end())
622 {
623 return NULL;
624 }
625 else
626 {
627 return framebuffer->second;
628 }
629}
630
631Renderbuffer *Context::getRenderbuffer(unsigned int handle)
632{
633 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000634
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635 if (renderbuffer == mRenderbufferMap.end())
636 {
637 return NULL;
638 }
639 else
640 {
641 return renderbuffer->second;
642 }
643}
644
645Colorbuffer *Context::getColorbuffer(GLuint handle)
646{
647 if (handle != 0)
648 {
649 Renderbuffer *renderbuffer = getRenderbuffer(handle);
650
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000651 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652 {
653 return static_cast<Colorbuffer*>(renderbuffer);
654 }
655 }
656 else // Special case: 0 refers to different initial render targets based on the attachment type
657 {
658 return mColorbufferZero;
659 }
660
661 return NULL;
662}
663
664Depthbuffer *Context::getDepthbuffer(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->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000671 {
672 return static_cast<Depthbuffer*>(renderbuffer);
673 }
674 }
675 else // Special case: 0 refers to different initial render targets based on the attachment type
676 {
677 return mDepthbufferZero;
678 }
679
680 return NULL;
681}
682
683Stencilbuffer *Context::getStencilbuffer(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->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000690 {
691 return static_cast<Stencilbuffer*>(renderbuffer);
692 }
693 }
694 else
695 {
696 return mStencilbufferZero;
697 }
698
699 return NULL;
700}
701
702Buffer *Context::getArrayBuffer()
703{
704 return getBuffer(arrayBuffer);
705}
706
707Buffer *Context::getElementArrayBuffer()
708{
709 return getBuffer(elementArrayBuffer);
710}
711
712Program *Context::getCurrentProgram()
713{
714 return getProgram(currentProgram);
715}
716
717Texture2D *Context::getTexture2D()
718{
719 if (texture2D == 0) // Special case: 0 refers to different initial textures based on the target
720 {
721 return mTexture2DZero;
722 }
723
724 return (Texture2D*)getTexture(texture2D);
725}
726
727TextureCubeMap *Context::getTextureCubeMap()
728{
729 if (textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
730 {
731 return mTextureCubeMapZero;
732 }
733
734 return (TextureCubeMap*)getTexture(textureCubeMap);
735}
736
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000737Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738{
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000739 return getTexture(samplerTexture[type][sampler]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000740}
741
742Framebuffer *Context::getFramebuffer()
743{
744 return getFramebuffer(framebuffer);
745}
746
747// Applies the render target surface, depth stencil surface, viewport rectangle and
748// scissor rectangle to the Direct3D 9 device
749bool Context::applyRenderTarget(bool ignoreViewport)
750{
751 IDirect3DDevice9 *device = getDevice();
752 Framebuffer *framebufferObject = getFramebuffer();
753
754 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
755 {
756 return false;
757 }
758
759 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
760 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
761
762 device->SetRenderTarget(0, renderTarget);
763 device->SetDepthStencilSurface(depthStencil);
764
765 D3DVIEWPORT9 viewport;
766 D3DSURFACE_DESC desc;
767 renderTarget->GetDesc(&desc);
768
769 if (ignoreViewport)
770 {
771 viewport.X = 0;
772 viewport.Y = 0;
773 viewport.Width = desc.Width;
774 viewport.Height = desc.Height;
775 viewport.MinZ = 0.0f;
776 viewport.MaxZ = 1.0f;
777 }
778 else
779 {
daniel@transgaming.com16973022010-03-11 19:22:19 +0000780 viewport.X = std::max(viewportX, 0);
781 viewport.Y = std::max(viewportY, 0);
782 viewport.Width = std::min(viewportWidth, (int)desc.Width - (int)viewport.X);
783 viewport.Height = std::min(viewportHeight, (int)desc.Height - (int)viewport.Y);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000784 viewport.MinZ = clamp01(zNear);
785 viewport.MaxZ = clamp01(zFar);
786 }
787
788 device->SetViewport(&viewport);
789
790 if (scissorTest)
791 {
792 RECT rect = {scissorX,
793 scissorY,
794 scissorX + scissorWidth,
795 scissorY + scissorHeight};
796
797 device->SetScissorRect(&rect);
798 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
799 }
800 else
801 {
802 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
803 }
804
805 if (currentProgram)
806 {
807 D3DSURFACE_DESC description;
808 renderTarget->GetDesc(&description);
809 Program *programObject = getCurrentProgram();
810
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000811 GLint halfPixelSize = programObject->getUniformLocation("gl_HalfPixelSize");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000812 GLfloat xy[2] = {1.0f / description.Width, 1.0f / description.Height};
813 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000814
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000815 GLint window = programObject->getUniformLocation("gl_Window");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000816 GLfloat whxy[4] = {viewportWidth / 2.0f, viewportHeight / 2.0f, (float)viewportX + viewportWidth / 2.0f, (float)viewportY + viewportHeight / 2.0f};
817 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
818
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000819 GLint depth = programObject->getUniformLocation("gl_Depth");
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000820 GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
821 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
822
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000823 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000824 programObject->setUniform1fv(near, 1, &zNear);
825
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000826 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000827 programObject->setUniform1fv(far, 1, &zFar);
828
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000829 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000830 GLfloat zDiff = zFar - zNear;
831 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000832 }
833
834 return true;
835}
836
837// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
838void Context::applyState()
839{
840 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +0000841 Program *programObject = getCurrentProgram();
842
843 GLint frontCCW = programObject->getUniformLocation("__frontCCW");
844 GLint ccw = (frontFace == GL_CCW);
845 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000846
847 if (cullFace)
848 {
849 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(cullMode, frontFace));
850 }
851 else
852 {
853 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
854 }
855
856 if (depthTest)
857 {
858 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
859 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(depthFunc));
860 }
861 else
862 {
863 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
864 }
865
866 if (blend)
867 {
868 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
869
870 if (sourceBlendRGB != GL_CONSTANT_ALPHA && sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
871 destBlendRGB != GL_CONSTANT_ALPHA && destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
872 {
873 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(blendColor));
874 }
875 else
876 {
877 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(blendColor.alpha),
878 unorm<8>(blendColor.alpha),
879 unorm<8>(blendColor.alpha),
880 unorm<8>(blendColor.alpha)));
881 }
882
883 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(sourceBlendRGB));
884 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(destBlendRGB));
885 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(blendEquationRGB));
886
887 if (sourceBlendRGB != sourceBlendAlpha || destBlendRGB != destBlendAlpha || blendEquationRGB != blendEquationAlpha)
888 {
889 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
890
891 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(sourceBlendAlpha));
892 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(destBlendAlpha));
893 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(blendEquationAlpha));
894
895 }
896 else
897 {
898 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
899 }
900 }
901 else
902 {
903 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
904 }
905
906 if (stencilTest)
907 {
908 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
909 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
910
911 // FIXME: Unsupported by D3D9
912 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
913 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
914 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
daniel@transgaming.com1436e262010-03-17 03:58:56 +0000915 if(stencilWritemask != stencilBackWritemask || stencilRef != stencilBackRef || stencilMask != stencilBackMask)
916 {
917 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
918 return error(GL_INVALID_OPERATION);
919 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920
921 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWritemask);
922 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilFunc));
923
924 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilRef); // FIXME: Clamp to range
925 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
926
927 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilFail));
928 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilPassDepthFail));
929 device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilPassDepthPass));
930
931 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWritemask);
932 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilBackFunc));
933
934 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilBackRef); // FIXME: Clamp to range
935 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilBackMask);
936
937 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilBackFail));
938 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilBackPassDepthFail));
939 device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilBackPassDepthPass));
940 }
941 else
942 {
943 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
944 }
945
946 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha));
947 device->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
948
949 if (polygonOffsetFill)
950 {
951 UNIMPLEMENTED(); // FIXME
952 }
953
954 if (sampleAlphaToCoverage)
955 {
956 UNIMPLEMENTED(); // FIXME
957 }
958
959 if (sampleCoverage)
960 {
961 UNIMPLEMENTED(); // FIXME: Ignore when SAMPLE_BUFFERS is not one
962 }
963
964 device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
965}
966
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000967// Fill in the programAttribute field of the array of TranslatedAttributes based on the active GLSL program.
968void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000969{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000970 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000971 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000972 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000973 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000974 attributes[i].programAttribute = getCurrentProgram()->getInputMapping(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000975 }
976 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000977}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000978
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000979// The indices parameter to glDrawElements can have two interpretations:
980// - as a pointer into client memory
981// - as an offset into the current GL_ELEMENT_ARRAY_BUFFER buffer
982// Handle these cases here and return a pointer to the index data.
983const Index *Context::adjustIndexPointer(const void *indices)
984{
985 if (elementArrayBuffer)
986 {
987 Buffer *buffer = getBuffer(elementArrayBuffer);
988 return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
989 }
990 else
991 {
992 return static_cast<const Index*>(indices);
993 }
994}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000995
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000996void Context::applyVertexBuffer(GLint first, GLsizei count)
997{
998 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
999
1000 mVertexDataManager->preRenderValidate(first, count, translated);
1001
1002 lookupAttributeMapping(translated);
1003
1004 mBufferBackEnd->preDraw(translated);
1005}
1006
1007void Context::applyVertexBuffer(GLsizei count, const void *indices, GLenum indexType)
1008{
1009 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1010
1011 mVertexDataManager->preRenderValidate(adjustIndexPointer(indices), count, translated);
1012
1013 lookupAttributeMapping(translated);
1014
1015 mBufferBackEnd->preDraw(translated);
1016}
1017
1018// Applies the indices and element array bindings to the Direct3D 9 device
1019void Context::applyIndexBuffer(const void *indices, GLsizei count)
1020{
1021 GLsizei length = count * sizeof(Index);
1022
1023 IDirect3DDevice9 *device = getDevice();
1024
1025 IDirect3DIndexBuffer9 *indexBuffer = NULL;
1026 void *data;
1027
1028 HRESULT result = device->CreateIndexBuffer(length, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexBuffer, NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001029
1030 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1031 {
1032 return error(GL_OUT_OF_MEMORY);
1033 }
1034
1035 ASSERT(SUCCEEDED(result));
1036
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001037 if (indexBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001038 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001039 indexBuffer->Lock(0, length, &data, 0);
1040 memcpy(data, adjustIndexPointer(indices), length);
1041 indexBuffer->Unlock();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001042
1043 device->SetIndices(indexBuffer);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001044 indexBuffer->Release(); // Will only effectively be deleted when no longer in use
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001045 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001046
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001047 startIndex = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001048}
1049
1050// Applies the shaders and shader constants to the Direct3D 9 device
1051void Context::applyShaders()
1052{
1053 IDirect3DDevice9 *device = getDevice();
1054 Program *programObject = getCurrentProgram();
1055 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1056 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1057
1058 device->SetVertexShader(vertexShader);
1059 device->SetPixelShader(pixelShader);
1060
1061 programObject->applyUniforms();
1062}
1063
1064// Applies the textures and sampler states to the Direct3D 9 device
1065void Context::applyTextures()
1066{
1067 IDirect3DDevice9 *device = getDevice();
1068 Program *programObject = getCurrentProgram();
1069
1070 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1071 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001072 int textureUnit = programObject->getSamplerMapping(sampler);
1073 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001074 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001075 SamplerType textureType = programObject->getSamplerType(sampler);
1076
1077 Texture *texture = getSamplerTexture(textureUnit, textureType);
1078
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001079 if (texture->isComplete())
1080 {
1081 GLenum wrapS = texture->getWrapS();
1082 GLenum wrapT = texture->getWrapT();
1083 GLenum minFilter = texture->getMinFilter();
1084 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001085
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001086 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1087 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001088
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001089 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1090 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1091 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1092 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1093 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001094
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001095 device->SetTexture(sampler, texture->getTexture());
1096 }
1097 else
1098 {
1099 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001101 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001102 else
1103 {
1104 device->SetTexture(sampler, NULL);
1105 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001106 }
1107}
1108
1109void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1110{
1111 Framebuffer *framebuffer = getFramebuffer();
1112 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1113 IDirect3DDevice9 *device = getDevice();
1114
1115 D3DSURFACE_DESC desc;
1116 renderTarget->GetDesc(&desc);
1117
1118 IDirect3DSurface9 *systemSurface;
1119 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1120
1121 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1122 {
1123 return error(GL_OUT_OF_MEMORY);
1124 }
1125
1126 ASSERT(SUCCEEDED(result));
1127
1128 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1129 {
1130 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1131 }
1132
1133 result = device->GetRenderTargetData(renderTarget, systemSurface);
1134
1135 if (result == D3DERR_DRIVERINTERNALERROR)
1136 {
1137 systemSurface->Release();
1138
1139 return error(GL_OUT_OF_MEMORY);
1140 }
1141
1142 if (FAILED(result))
1143 {
1144 UNREACHABLE();
1145 systemSurface->Release();
1146
1147 return; // No sensible error to generate
1148 }
1149
1150 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001151 RECT rect = {std::max(x, 0),
1152 std::max(y, 0),
1153 std::min(x + width, (int)desc.Width),
1154 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001155
1156 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1157
1158 if (FAILED(result))
1159 {
1160 UNREACHABLE();
1161 systemSurface->Release();
1162
1163 return; // No sensible error to generate
1164 }
1165
1166 unsigned char *source = (unsigned char*)lock.pBits;
1167 unsigned char *dest = (unsigned char*)pixels;
1168
1169 for (int j = 0; j < rect.bottom - rect.top; j++)
1170 {
1171 for (int i = 0; i < rect.right - rect.left; i++)
1172 {
1173 float r;
1174 float g;
1175 float b;
1176 float a;
1177
1178 switch (desc.Format)
1179 {
1180 case D3DFMT_R5G6B5:
1181 {
1182 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1183
1184 a = 1.0f;
1185 b = (rgb & 0x001F) * (1.0f / 0x001F);
1186 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1187 r = (rgb & 0xF800) * (1.0f / 0xF800);
1188 }
1189 break;
1190 case D3DFMT_X1R5G5B5:
1191 {
1192 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1193
1194 a = 1.0f;
1195 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1196 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1197 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1198 }
1199 break;
1200 case D3DFMT_A1R5G5B5:
1201 {
1202 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1203
1204 a = (argb & 0x8000) ? 1.0f : 0.0f;
1205 b = (argb & 0x001F) * (1.0f / 0x001F);
1206 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1207 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1208 }
1209 break;
1210 case D3DFMT_A8R8G8B8:
1211 {
1212 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1213
1214 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1215 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1216 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1217 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1218 }
1219 break;
1220 case D3DFMT_X8R8G8B8:
1221 {
1222 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1223
1224 a = 1.0f;
1225 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
1226 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
1227 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
1228 }
1229 break;
1230 case D3DFMT_A2R10G10B10:
1231 {
1232 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1233
1234 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
1235 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
1236 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
1237 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
1238 }
1239 break;
1240 default:
1241 UNIMPLEMENTED(); // FIXME
1242 UNREACHABLE();
1243 }
1244
1245 switch (format)
1246 {
1247 case GL_RGBA:
1248 switch (type)
1249 {
1250 case GL_UNSIGNED_BYTE:
1251 dest[4 * (i + j * width) + 0] = (unsigned char)(255 * r + 0.5f);
1252 dest[4 * (i + j * width) + 1] = (unsigned char)(255 * g + 0.5f);
1253 dest[4 * (i + j * width) + 2] = (unsigned char)(255 * b + 0.5f);
1254 dest[4 * (i + j * width) + 3] = (unsigned char)(255 * a + 0.5f);
1255 break;
1256 default: UNREACHABLE();
1257 }
1258 break;
1259 case IMPLEMENTATION_COLOR_READ_FORMAT:
1260 switch (type)
1261 {
1262 case IMPLEMENTATION_COLOR_READ_TYPE:
1263 break;
1264 default: UNREACHABLE();
1265 }
1266 break;
1267 default: UNREACHABLE();
1268 }
1269 }
1270 }
1271
1272 systemSurface->UnlockRect();
1273
1274 systemSurface->Release();
1275}
1276
1277void Context::clear(GLbitfield mask)
1278{
1279 IDirect3DDevice9 *device = getDevice();
1280 DWORD flags = 0;
1281
1282 if (mask & GL_COLOR_BUFFER_BIT)
1283 {
1284 mask &= ~GL_COLOR_BUFFER_BIT;
1285 flags |= D3DCLEAR_TARGET;
1286 }
1287
1288 if (mask & GL_DEPTH_BUFFER_BIT)
1289 {
1290 mask &= ~GL_DEPTH_BUFFER_BIT;
1291 if (depthMask)
1292 {
1293 flags |= D3DCLEAR_ZBUFFER;
1294 }
1295 }
1296
1297 Framebuffer *framebufferObject = getFramebuffer();
1298 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1299
1300 GLuint stencilUnmasked = 0x0;
1301
1302 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
1303 {
1304 D3DSURFACE_DESC desc;
1305 depthStencil->GetDesc(&desc);
1306
1307 mask &= ~GL_STENCIL_BUFFER_BIT;
1308 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
1309 stencilUnmasked = (0x1 << stencilSize) - 1;
1310
1311 if (stencilUnmasked != 0x0)
1312 {
1313 flags |= D3DCLEAR_STENCIL;
1314 }
1315 }
1316
1317 if (mask != 0)
1318 {
1319 return error(GL_INVALID_VALUE);
1320 }
1321
1322 applyRenderTarget(true); // Clips the clear to the scissor rectangle but not the viewport
1323
1324 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(colorClearValue.alpha), unorm<8>(colorClearValue.red), unorm<8>(colorClearValue.green), unorm<8>(colorClearValue.blue));
1325 float depth = clamp01(depthClearValue);
1326 int stencil = stencilClearValue & 0x000000FF;
1327
1328 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1329
1330 D3DSURFACE_DESC desc;
1331 renderTarget->GetDesc(&desc);
1332
1333 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || colorMaskAlpha;
1334
1335 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
1336 (stencilWritemask & stencilUnmasked) != stencilUnmasked;
1337 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001338 !(colorMaskRed && colorMaskGreen &&
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001339 colorMaskBlue && alphaUnmasked);
1340
1341 if (needMaskedColorClear || needMaskedStencilClear)
1342 {
1343 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1344 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1345 device->SetRenderState(D3DRS_ZENABLE, FALSE);
1346 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1347 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1348 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1349 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1350 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1351
1352 if (flags & D3DCLEAR_TARGET)
1353 {
1354 device->SetRenderState(D3DRS_COLORWRITEENABLE, (colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
1355 (colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
1356 (colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
1357 (colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
1358 }
1359 else
1360 {
1361 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1362 }
1363
1364 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
1365 {
1366 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1367 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
1368 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
1369 device->SetRenderState(D3DRS_STENCILREF, stencil);
1370 device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001371 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001372 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
1373 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
1374 }
1375 else
1376 {
1377 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1378 }
1379
1380 device->SetPixelShader(NULL);
1381 device->SetVertexShader(NULL);
1382 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1383
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001384 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001385 {
1386 float x, y, z, w;
1387 D3DCOLOR diffuse;
1388 };
1389
1390 Vertex quad[4];
1391 quad[0].x = 0.0f;
1392 quad[0].y = (float)desc.Height;
1393 quad[0].z = 0.0f;
1394 quad[0].w = 1.0f;
1395 quad[0].diffuse = color;
1396
1397 quad[1].x = (float)desc.Width;
1398 quad[1].y = (float)desc.Height;
1399 quad[1].z = 0.0f;
1400 quad[1].w = 1.0f;
1401 quad[1].diffuse = color;
1402
1403 quad[2].x = 0.0f;
1404 quad[2].y = 0.0f;
1405 quad[2].z = 0.0f;
1406 quad[2].w = 1.0f;
1407 quad[2].diffuse = color;
1408
1409 quad[3].x = (float)desc.Width;
1410 quad[3].y = 0.0f;
1411 quad[3].z = 0.0f;
1412 quad[3].w = 1.0f;
1413 quad[3].diffuse = color;
1414
1415 device->BeginScene();
1416 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
1417 device->EndScene();
1418
1419 if (flags & D3DCLEAR_ZBUFFER)
1420 {
1421 device->SetRenderState(D3DRS_ZENABLE, TRUE);
1422 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1423 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
1424 }
1425 }
1426 else
1427 {
1428 device->Clear(0, NULL, flags, color, depth, stencil);
1429 }
1430}
1431
1432void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
1433{
1434 if (!currentProgram)
1435 {
1436 return error(GL_INVALID_OPERATION);
1437 }
1438
1439 IDirect3DDevice9 *device = getDevice();
1440 D3DPRIMITIVETYPE primitiveType;
1441 int primitiveCount;
1442
1443 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1444 return error(GL_INVALID_ENUM);
1445
1446 if (primitiveCount <= 0)
1447 {
1448 return;
1449 }
1450
1451 if (!applyRenderTarget(false))
1452 {
1453 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1454 }
1455
1456 applyState();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001457 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001458 applyShaders();
1459 applyTextures();
1460
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001461 if (!cullSkipsDraw(mode))
1462 {
1463 device->BeginScene();
1464 device->DrawPrimitive(primitiveType, first, primitiveCount);
1465 device->EndScene();
1466 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001467}
1468
1469void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
1470{
1471 if (!currentProgram)
1472 {
1473 return error(GL_INVALID_OPERATION);
1474 }
1475
1476 if (!indices && !elementArrayBuffer)
1477 {
1478 return error(GL_INVALID_OPERATION);
1479 }
1480
1481 IDirect3DDevice9 *device = getDevice();
1482 D3DPRIMITIVETYPE primitiveType;
1483 int primitiveCount;
1484
1485 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
1486 return error(GL_INVALID_ENUM);
1487
1488 if (primitiveCount <= 0)
1489 {
1490 return;
1491 }
1492
1493 if (!applyRenderTarget(false))
1494 {
1495 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1496 }
1497
1498 applyState();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001499 applyVertexBuffer(count, indices, type);
1500 applyIndexBuffer(indices, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001501 applyShaders();
1502 applyTextures();
1503
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001504 if (!cullSkipsDraw(mode))
1505 {
1506 device->BeginScene();
1507 device->DrawIndexedPrimitive(primitiveType, 0, 0, count, startIndex, primitiveCount);
1508 device->EndScene();
1509 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001510}
1511
1512void Context::finish()
1513{
1514 IDirect3DDevice9 *device = getDevice();
1515 IDirect3DQuery9 *occlusionQuery = NULL;
1516
1517 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
1518
1519 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1520 {
1521 return error(GL_OUT_OF_MEMORY);
1522 }
1523
1524 ASSERT(SUCCEEDED(result));
1525
1526 if (occlusionQuery)
1527 {
1528 occlusionQuery->Issue(D3DISSUE_BEGIN);
1529
1530 // Render something outside the render target
1531 device->SetPixelShader(NULL);
1532 device->SetVertexShader(NULL);
1533 device->SetFVF(D3DFVF_XYZRHW);
1534 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
1535 device->BeginScene();
1536 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
1537 device->EndScene();
1538
1539 occlusionQuery->Issue(D3DISSUE_END);
1540
1541 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1542 {
1543 // Keep polling, but allow other threads to do something useful first
1544 Sleep(0);
1545 }
1546
1547 occlusionQuery->Release();
1548 }
1549}
1550
1551void Context::flush()
1552{
1553 IDirect3DDevice9 *device = getDevice();
1554 IDirect3DQuery9 *eventQuery = NULL;
1555
1556 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
1557
1558 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1559 {
1560 return error(GL_OUT_OF_MEMORY);
1561 }
1562
1563 ASSERT(SUCCEEDED(result));
1564
1565 if (eventQuery)
1566 {
1567 eventQuery->Issue(D3DISSUE_END);
1568
1569 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
1570 {
1571 // Keep polling, but allow other threads to do something useful first
1572 Sleep(0);
1573 }
1574
1575 eventQuery->Release();
1576 }
1577}
1578
1579void Context::recordInvalidEnum()
1580{
1581 mInvalidEnum = true;
1582}
1583
1584void Context::recordInvalidValue()
1585{
1586 mInvalidValue = true;
1587}
1588
1589void Context::recordInvalidOperation()
1590{
1591 mInvalidOperation = true;
1592}
1593
1594void Context::recordOutOfMemory()
1595{
1596 mOutOfMemory = true;
1597}
1598
1599void Context::recordInvalidFramebufferOperation()
1600{
1601 mInvalidFramebufferOperation = true;
1602}
1603
1604// Get one of the recorded errors and clear its flag, if any.
1605// [OpenGL ES 2.0.24] section 2.5 page 13.
1606GLenum Context::getError()
1607{
1608 if (mInvalidEnum)
1609 {
1610 mInvalidEnum = false;
1611
1612 return GL_INVALID_ENUM;
1613 }
1614
1615 if (mInvalidValue)
1616 {
1617 mInvalidValue = false;
1618
1619 return GL_INVALID_VALUE;
1620 }
1621
1622 if (mInvalidOperation)
1623 {
1624 mInvalidOperation = false;
1625
1626 return GL_INVALID_OPERATION;
1627 }
1628
1629 if (mOutOfMemory)
1630 {
1631 mOutOfMemory = false;
1632
1633 return GL_OUT_OF_MEMORY;
1634 }
1635
1636 if (mInvalidFramebufferOperation)
1637 {
1638 mInvalidFramebufferOperation = false;
1639
1640 return GL_INVALID_FRAMEBUFFER_OPERATION;
1641 }
1642
1643 return GL_NO_ERROR;
1644}
1645
1646void Context::detachBuffer(GLuint buffer)
1647{
1648 // [OpenGL ES 2.0.24] section 2.9 page 22:
1649 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
1650 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
1651
1652 if (arrayBuffer == buffer)
1653 {
1654 arrayBuffer = 0;
1655 }
1656
1657 if (elementArrayBuffer == buffer)
1658 {
1659 elementArrayBuffer = 0;
1660 }
1661
1662 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
1663 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001664 if (vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001665 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001666 vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001667 }
1668 }
1669}
1670
1671void Context::detachTexture(GLuint texture)
1672{
1673 // [OpenGL ES 2.0.24] section 3.8 page 84:
1674 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
1675 // rebound to texture object zero
1676
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001677 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001678 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001679 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001680 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001681 if (samplerTexture[type][sampler] == texture)
1682 {
1683 samplerTexture[type][sampler] = 0;
1684 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001685 }
1686 }
1687
1688 // [OpenGL ES 2.0.24] section 4.4 page 112:
1689 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
1690 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
1691 // image was attached in the currently bound framebuffer.
1692
1693 Framebuffer *framebuffer = getFramebuffer();
1694
1695 if (framebuffer)
1696 {
1697 framebuffer->detachTexture(texture);
1698 }
1699}
1700
1701void Context::detachFramebuffer(GLuint framebuffer)
1702{
1703 // [OpenGL ES 2.0.24] section 4.4 page 107:
1704 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
1705 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
1706
1707 if (this->framebuffer == framebuffer)
1708 {
1709 bindFramebuffer(0);
1710 }
1711}
1712
1713void Context::detachRenderbuffer(GLuint renderbuffer)
1714{
1715 // [OpenGL ES 2.0.24] section 4.4 page 109:
1716 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
1717 // had been executed with the target RENDERBUFFER and name of zero.
1718
1719 if (this->renderbuffer == renderbuffer)
1720 {
1721 bindRenderbuffer(0);
1722 }
1723
1724 // [OpenGL ES 2.0.24] section 4.4 page 111:
1725 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
1726 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
1727 // point to which this image was attached in the currently bound framebuffer.
1728
1729 Framebuffer *framebuffer = getFramebuffer();
1730
1731 if (framebuffer)
1732 {
1733 framebuffer->detachRenderbuffer(renderbuffer);
1734 }
1735}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001736
1737Texture *Context::getIncompleteTexture(SamplerType type)
1738{
1739 Texture *t = mIncompleteTextures[type];
1740
1741 if (t == NULL)
1742 {
1743 static const GLubyte color[] = { 0, 0, 0, 255 };
1744
1745 switch (type)
1746 {
1747 default:
1748 UNREACHABLE();
1749 // default falls through to SAMPLER_2D
1750
1751 case SAMPLER_2D:
1752 {
1753 Texture2D *incomplete2d = new Texture2D;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001754 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001755 t = incomplete2d;
1756 }
1757 break;
1758
1759 case SAMPLER_CUBE:
1760 {
1761 TextureCubeMap *incompleteCube = new TextureCubeMap;
1762
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001763 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1764 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1765 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1766 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1767 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
1768 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001769
1770 t = incompleteCube;
1771 }
1772 break;
1773 }
1774
1775 mIncompleteTextures[type] = t;
1776 }
1777
1778 return t;
1779}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00001780
1781bool Context::cullSkipsDraw(GLenum primitiveType)
1782{
1783 if (cullFace && cullMode == GL_FRONT_AND_BACK &&
1784 (primitiveType == GL_TRIANGLES || primitiveType == GL_TRIANGLE_FAN || primitiveType == GL_TRIANGLE_STRIP))
1785 {
1786 return true;
1787 }
1788 else
1789 {
1790 return false;
1791 }
1792}
1793
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001794}
1795
1796extern "C"
1797{
1798gl::Context *glCreateContext(const egl::Config *config)
1799{
1800 return new gl::Context(config);
1801}
1802
1803void glDestroyContext(gl::Context *context)
1804{
1805 delete context;
1806
1807 if (context == gl::getContext())
1808 {
1809 gl::makeCurrent(NULL, NULL, NULL);
1810 }
1811}
1812
1813void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
1814{
1815 gl::makeCurrent(context, display, surface);
1816}
1817
1818gl::Context *glGetCurrentContext()
1819{
1820 return gl::getContext();
1821}
1822}