diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /opengl/libagl/array.cpp | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'opengl/libagl/array.cpp')
-rw-r--r-- | opengl/libagl/array.cpp | 1557 |
1 files changed, 0 insertions, 1557 deletions
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp deleted file mode 100644 index 8fa7566..0000000 --- a/opengl/libagl/array.cpp +++ /dev/null @@ -1,1557 +0,0 @@ -/* -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include <stdlib.h> -#include <stdio.h> - -#include "context.h" -#include "fp.h" -#include "state.h" -#include "matrix.h" -#include "vertex.h" -#include "light.h" -#include "primitives.h" -#include "texture.h" -#include "BufferObjectManager.h" - -// ---------------------------------------------------------------------------- - -#define VC_CACHE_STATISTICS 0 -#define VC_CACHE_TYPE_NONE 0 -#define VC_CACHE_TYPE_INDEXED 1 -#define VC_CACHE_TYPE_LRU 2 -#define VC_CACHE_TYPE VC_CACHE_TYPE_INDEXED - -#if VC_CACHE_STATISTICS -#include <utils/Timers.h> -#endif - -// ---------------------------------------------------------------------------- - -namespace android { - -static void validate_arrays(ogles_context_t* c, GLenum mode); - -static void compileElements__generic(ogles_context_t*, - vertex_t*, GLint, GLsizei); -static void compileElement__generic(ogles_context_t*, - vertex_t*, GLint); - -static void drawPrimitivesPoints(ogles_context_t*, GLint, GLsizei); -static void drawPrimitivesLineStrip(ogles_context_t*, GLint, GLsizei); -static void drawPrimitivesLineLoop(ogles_context_t*, GLint, GLsizei); -static void drawPrimitivesLines(ogles_context_t*, GLint, GLsizei); -static void drawPrimitivesTriangleStrip(ogles_context_t*, GLint, GLsizei); -static void drawPrimitivesTriangleFan(ogles_context_t*, GLint, GLsizei); -static void drawPrimitivesTriangles(ogles_context_t*, GLint, GLsizei); - -static void drawIndexedPrimitivesPoints(ogles_context_t*, - GLsizei, const GLvoid*); -static void drawIndexedPrimitivesLineStrip(ogles_context_t*, - GLsizei, const GLvoid*); -static void drawIndexedPrimitivesLineLoop(ogles_context_t*, - GLsizei, const GLvoid*); -static void drawIndexedPrimitivesLines(ogles_context_t*, - GLsizei, const GLvoid*); -static void drawIndexedPrimitivesTriangleStrip(ogles_context_t*, - GLsizei, const GLvoid*); -static void drawIndexedPrimitivesTriangleFan(ogles_context_t*, - GLsizei, const GLvoid*); -static void drawIndexedPrimitivesTriangles(ogles_context_t*, - GLsizei, const GLvoid*); - -// ---------------------------------------------------------------------------- - -typedef void (*arrays_prims_fct_t)(ogles_context_t*, GLint, GLsizei); -static const arrays_prims_fct_t drawArraysPrims[] = { - drawPrimitivesPoints, - drawPrimitivesLines, - drawPrimitivesLineLoop, - drawPrimitivesLineStrip, - drawPrimitivesTriangles, - drawPrimitivesTriangleStrip, - drawPrimitivesTriangleFan -}; - -typedef void (*elements_prims_fct_t)(ogles_context_t*, GLsizei, const GLvoid*); -static const elements_prims_fct_t drawElementsPrims[] = { - drawIndexedPrimitivesPoints, - drawIndexedPrimitivesLines, - drawIndexedPrimitivesLineLoop, - drawIndexedPrimitivesLineStrip, - drawIndexedPrimitivesTriangles, - drawIndexedPrimitivesTriangleStrip, - drawIndexedPrimitivesTriangleFan -}; - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -void ogles_init_array(ogles_context_t* c) -{ - c->arrays.vertex.size = 4; - c->arrays.vertex.type = GL_FLOAT; - c->arrays.color.size = 4; - c->arrays.color.type = GL_FLOAT; - c->arrays.normal.size = 4; - c->arrays.normal.type = GL_FLOAT; - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - c->arrays.texture[i].size = 4; - c->arrays.texture[i].type = GL_FLOAT; - } - c->vc.init(); - - if (!c->vc.vBuffer) { - // this could have failed - ogles_error(c, GL_OUT_OF_MEMORY); - } -} - -void ogles_uninit_array(ogles_context_t* c) -{ - c->vc.uninit(); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Array fetchers -#endif - -static void currentColor(ogles_context_t* c, GLfixed* v, const GLvoid*) { - memcpy(v, c->current.color.v, sizeof(vec4_t)); -} -static void currentColor_clamp(ogles_context_t* c, GLfixed* v, const GLvoid*) { - memcpy(v, c->currentColorClamped.v, sizeof(vec4_t)); -} -static void currentNormal(ogles_context_t* c, GLfixed* v, const GLvoid*) { - memcpy(v, c->currentNormal.v, sizeof(vec3_t)); -} -static void currentTexCoord(ogles_context_t* c, GLfixed* v, const GLvoid*) { - memcpy(v, c->current.texture[c->arrays.tmu].v, sizeof(vec4_t)); -} - - -static void fetchNop(ogles_context_t*, GLfixed*, const GLvoid*) { -} -static void fetch2b(ogles_context_t*, GLfixed* v, const GLbyte* p) { - v[0] = gglIntToFixed(p[0]); - v[1] = gglIntToFixed(p[1]); -} -static void fetch2s(ogles_context_t*, GLfixed* v, const GLshort* p) { - v[0] = gglIntToFixed(p[0]); - v[1] = gglIntToFixed(p[1]); -} -static void fetch2x(ogles_context_t*, GLfixed* v, const GLfixed* p) { - memcpy(v, p, 2*sizeof(GLfixed)); -} -static void fetch2f(ogles_context_t*, GLfixed* v, const GLfloat* p) { - v[0] = gglFloatToFixed(p[0]); - v[1] = gglFloatToFixed(p[1]); -} -static void fetch3b(ogles_context_t*, GLfixed* v, const GLbyte* p) { - v[0] = gglIntToFixed(p[0]); - v[1] = gglIntToFixed(p[1]); - v[2] = gglIntToFixed(p[2]); -} -static void fetch3s(ogles_context_t*, GLfixed* v, const GLshort* p) { - v[0] = gglIntToFixed(p[0]); - v[1] = gglIntToFixed(p[1]); - v[2] = gglIntToFixed(p[2]); -} -static void fetch3x(ogles_context_t*, GLfixed* v, const GLfixed* p) { - memcpy(v, p, 3*sizeof(GLfixed)); -} -static void fetch3f(ogles_context_t*, GLfixed* v, const GLfloat* p) { - v[0] = gglFloatToFixed(p[0]); - v[1] = gglFloatToFixed(p[1]); - v[2] = gglFloatToFixed(p[2]); -} -static void fetch4b(ogles_context_t*, GLfixed* v, const GLbyte* p) { - v[0] = gglIntToFixed(p[0]); - v[1] = gglIntToFixed(p[1]); - v[2] = gglIntToFixed(p[2]); - v[3] = gglIntToFixed(p[3]); -} -static void fetch4s(ogles_context_t*, GLfixed* v, const GLshort* p) { - v[0] = gglIntToFixed(p[0]); - v[1] = gglIntToFixed(p[1]); - v[2] = gglIntToFixed(p[2]); - v[3] = gglIntToFixed(p[3]); -} -static void fetch4x(ogles_context_t*, GLfixed* v, const GLfixed* p) { - memcpy(v, p, 4*sizeof(GLfixed)); -} -static void fetch4f(ogles_context_t*, GLfixed* v, const GLfloat* p) { - v[0] = gglFloatToFixed(p[0]); - v[1] = gglFloatToFixed(p[1]); - v[2] = gglFloatToFixed(p[2]); - v[3] = gglFloatToFixed(p[3]); -} -static void fetchExpand4ub(ogles_context_t*, GLfixed* v, const GLubyte* p) { - v[0] = GGL_UB_TO_X(p[0]); - v[1] = GGL_UB_TO_X(p[1]); - v[2] = GGL_UB_TO_X(p[2]); - v[3] = GGL_UB_TO_X(p[3]); -} -static void fetchClamp4x(ogles_context_t*, GLfixed* v, const GLfixed* p) { - v[0] = gglClampx(p[0]); - v[1] = gglClampx(p[1]); - v[2] = gglClampx(p[2]); - v[3] = gglClampx(p[3]); -} -static void fetchClamp4f(ogles_context_t*, GLfixed* v, const GLfloat* p) { - v[0] = gglClampx(gglFloatToFixed(p[0])); - v[1] = gglClampx(gglFloatToFixed(p[1])); - v[2] = gglClampx(gglFloatToFixed(p[2])); - v[3] = gglClampx(gglFloatToFixed(p[3])); -} -static void fetchExpand3ub(ogles_context_t*, GLfixed* v, const GLubyte* p) { - v[0] = GGL_UB_TO_X(p[0]); - v[1] = GGL_UB_TO_X(p[1]); - v[2] = GGL_UB_TO_X(p[2]); - v[3] = 0x10000; -} -static void fetchClamp3x(ogles_context_t*, GLfixed* v, const GLfixed* p) { - v[0] = gglClampx(p[0]); - v[1] = gglClampx(p[1]); - v[2] = gglClampx(p[2]); - v[3] = 0x10000; -} -static void fetchClamp3f(ogles_context_t*, GLfixed* v, const GLfloat* p) { - v[0] = gglClampx(gglFloatToFixed(p[0])); - v[1] = gglClampx(gglFloatToFixed(p[1])); - v[2] = gglClampx(gglFloatToFixed(p[2])); - v[3] = 0x10000; -} -static void fetchExpand3b(ogles_context_t*, GLfixed* v, const GLbyte* p) { - v[0] = GGL_B_TO_X(p[0]); - v[1] = GGL_B_TO_X(p[1]); - v[2] = GGL_B_TO_X(p[2]); -} -static void fetchExpand3s(ogles_context_t*, GLfixed* v, const GLshort* p) { - v[0] = GGL_S_TO_X(p[0]); - v[1] = GGL_S_TO_X(p[1]); - v[2] = GGL_S_TO_X(p[2]); -} - -typedef array_t::fetcher_t fn_t; - -static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x} - { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0, - (fn_t)fetch3f, 0, 0, 0, 0, 0, - (fn_t)fetch3x }, - { 0, (fn_t)fetchExpand4ub, 0, 0, 0, 0, - (fn_t)fetch4f, 0, 0, 0, 0, 0, - (fn_t)fetch4x }, -}; -static const fn_t color_clamp_fct[2][16] = { // size={3,4}, type={ub,f,x} - { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0, - (fn_t)fetchClamp3f, 0, 0, 0, 0, 0, - (fn_t)fetchClamp3x }, - { 0, (fn_t)fetchExpand4ub, 0, 0, 0, 0, - (fn_t)fetchClamp4f, 0, 0, 0, 0, 0, - (fn_t)fetchClamp4x }, -}; -static const fn_t normal_fct[1][16] = { // size={3}, type={b,s,f,x} - { (fn_t)fetchExpand3b, 0, - (fn_t)fetchExpand3s, 0, 0, 0, - (fn_t)fetch3f, 0, 0, 0, 0, 0, - (fn_t)fetch3x }, -}; -static const fn_t vertex_fct[3][16] = { // size={2,3,4}, type={b,s,f,x} - { (fn_t)fetch2b, 0, - (fn_t)fetch2s, 0, 0, 0, - (fn_t)fetch2f, 0, 0, 0, 0, 0, - (fn_t)fetch3x }, - { (fn_t)fetch3b, 0, - (fn_t)fetch3s, 0, 0, 0, - (fn_t)fetch3f, 0, 0, 0, 0, 0, - (fn_t)fetch3x }, - { (fn_t)fetch4b, 0, - (fn_t)fetch4s, 0, 0, 0, - (fn_t)fetch4f, 0, 0, 0, 0, 0, - (fn_t)fetch4x } -}; -static const fn_t texture_fct[3][16] = { // size={2,3,4}, type={b,s,f,x} - { (fn_t)fetch2b, 0, - (fn_t)fetch2s, 0, 0, 0, - (fn_t)fetch2f, 0, 0, 0, 0, 0, - (fn_t)fetch2x }, - { (fn_t)fetch3b, 0, - (fn_t)fetch3s, 0, 0, 0, - (fn_t)fetch3f, 0, 0, 0, 0, 0, - (fn_t)fetch3x }, - { (fn_t)fetch4b, 0, - (fn_t)fetch4s, 0, 0, 0, - (fn_t)fetch4f, 0, 0, 0, 0, 0, - (fn_t)fetch4x } -}; - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark array_t -#endif - -void array_t::init( - GLint size, GLenum type, GLsizei stride, - const GLvoid *pointer, const buffer_t* bo, GLsizei count) -{ - if (!stride) { - stride = size; - switch (type) { - case GL_SHORT: - case GL_UNSIGNED_SHORT: - stride *= 2; - break; - case GL_FLOAT: - case GL_FIXED: - stride *= 4; - break; - } - } - this->size = size; - this->type = type; - this->stride = stride; - this->pointer = pointer; - this->bo = bo; - this->bounds = count; -} - -inline void array_t::resolve() -{ - physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer; -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark vertex_cache_t -#endif - -void vertex_cache_t::init() -{ - // make sure the size of vertex_t allows cache-line alignment - CTA<(sizeof(vertex_t) & 0x1F) == 0> assertAlignedSize; - - const int align = 32; - const size_t s = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE; - const size_t size = s*sizeof(vertex_t) + align; - base = malloc(size); - if (base) { - memset(base, 0, size); - vBuffer = (vertex_t*)((size_t(base) + align - 1) & ~(align-1)); - vCache = vBuffer + VERTEX_BUFFER_SIZE; - sequence = 0; - } -} - -void vertex_cache_t::uninit() -{ - free(base); - base = vBuffer = vCache = 0; -} - -void vertex_cache_t::clear() -{ -#if VC_CACHE_STATISTICS - startTime = systemTime(SYSTEM_TIME_THREAD); - total = 0; - misses = 0; -#endif - -#if VC_CACHE_TYPE == VC_CACHE_TYPE_LRU - vertex_t* v = vBuffer; - size_t count = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE; - do { - v->mru = 0; - v++; - } while (--count); -#endif - - sequence += INDEX_SEQ; - if (sequence >= 0x80000000LU) { - sequence = INDEX_SEQ; - vertex_t* v = vBuffer; - size_t count = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE; - do { - v->index = 0; - v++; - } while (--count); - } -} - -void vertex_cache_t::dump_stats(GLenum mode) -{ -#if VC_CACHE_STATISTICS - nsecs_t time = systemTime(SYSTEM_TIME_THREAD) - startTime; - uint32_t hits = total - misses; - uint32_t prim_count; - switch (mode) { - case GL_POINTS: prim_count = total; break; - case GL_LINE_STRIP: prim_count = total - 1; break; - case GL_LINE_LOOP: prim_count = total - 1; break; - case GL_LINES: prim_count = total / 2; break; - case GL_TRIANGLE_STRIP: prim_count = total - 2; break; - case GL_TRIANGLE_FAN: prim_count = total - 2; break; - case GL_TRIANGLES: prim_count = total / 3; break; - default: return; - } - printf( "total=%5u, hits=%5u, miss=%5u, hitrate=%3u%%," - " prims=%5u, time=%6u us, prims/s=%d, v/t=%f\n", - total, hits, misses, (hits*100)/total, - prim_count, int(ns2us(time)), int(prim_count*float(seconds(1))/time), - float(misses) / prim_count); -#endif -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -static __attribute__((noinline)) -void enableDisableClientState(ogles_context_t* c, GLenum array, bool enable) -{ - const int tmu = c->arrays.activeTexture; - array_t* a; - switch (array) { - case GL_COLOR_ARRAY: a = &c->arrays.color; break; - case GL_NORMAL_ARRAY: a = &c->arrays.normal; break; - case GL_TEXTURE_COORD_ARRAY: a = &c->arrays.texture[tmu]; break; - case GL_VERTEX_ARRAY: a = &c->arrays.vertex; break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - a->enable = enable ? GL_TRUE : GL_FALSE; -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Vertex Cache -#endif - -static __attribute__((noinline)) -vertex_t* cache_vertex(ogles_context_t* c, vertex_t* v, uint32_t index) -{ - #if VC_CACHE_STATISTICS - c->vc.misses++; - #endif - if (ggl_unlikely(v->locked)) { - // we're just looking for an entry in the cache that is not locked. - // and we know that there cannot be more than 2 locked entries - // because a triangle needs at most 3 vertices. - // We never use the first and second entries because they might be in - // use by the striper or faner. Any other entry will do as long as - // it's not locked. - // We compute directly the index of a "free" entry from the locked - // state of v[2] and v[3]. - v = c->vc.vBuffer + 2; - v += v[0].locked | (v[1].locked<<1); - } - // note: compileElement clears v->flags - c->arrays.compileElement(c, v, index); - v->locked = 1; - return v; -} - -static __attribute__((noinline)) -vertex_t* fetch_vertex(ogles_context_t* c, size_t index) -{ - index |= c->vc.sequence; - -#if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED - - vertex_t* const v = c->vc.vCache + - (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1)); - - if (ggl_likely(v->index == index)) { - v->locked = 1; - return v; - } - return cache_vertex(c, v, index); - -#elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU - - vertex_t* v = c->vc.vCache + - (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2; - - // always record LRU in v[0] - if (ggl_likely(v[0].index == index)) { - v[0].locked = 1; - v[0].mru = 0; - return &v[0]; - } - - if (ggl_likely(v[1].index == index)) { - v[1].locked = 1; - v[0].mru = 1; - return &v[1]; - } - - const int lru = 1 - v[0].mru; - v[0].mru = lru; - return cache_vertex(c, &v[lru], index); - -#elif VC_CACHE_TYPE == VC_CACHE_TYPE_NONE - - // just for debugging... - vertex_t* v = c->vc.vBuffer + 2; - return cache_vertex(c, v, index); - -#endif -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Primitive Assembly -#endif - -void drawPrimitivesPoints(ogles_context_t* c, GLint first, GLsizei count) -{ - if (ggl_unlikely(count < 1)) - return; - - // vertex cache size must be multiple of 1 - const GLsizei vcs = - (vertex_cache_t::VERTEX_BUFFER_SIZE + - vertex_cache_t::VERTEX_CACHE_SIZE); - do { - vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; - c->arrays.cull = vertex_t::CLIP_ALL; - c->arrays.compileElements(c, v, first, num); - first += num; - count -= num; - if (!c->arrays.cull) { - // quick/trivial reject of the whole batch - do { - const uint32_t cc = v[0].flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderPoint(c, v); - v++; - num--; - } while (num); - } - } while (count); -} - -// ---------------------------------------------------------------------------- - -void drawPrimitivesLineStrip(ogles_context_t* c, GLint first, GLsizei count) -{ - if (ggl_unlikely(count < 2)) - return; - - vertex_t *v, *v0, *v1; - c->arrays.cull = vertex_t::CLIP_ALL; - c->arrays.compileElement(c, c->vc.vBuffer, first); - first += 1; - count -= 1; - - // vertex cache size must be multiple of 1 - const GLsizei vcs = - (vertex_cache_t::VERTEX_BUFFER_SIZE + - vertex_cache_t::VERTEX_CACHE_SIZE - 1); - do { - v0 = c->vc.vBuffer + 0; - v = c->vc.vBuffer + 1; - GLsizei num = count > vcs ? vcs : count; - c->arrays.compileElements(c, v, first, num); - first += num; - count -= num; - if (!c->arrays.cull) { - // quick/trivial reject of the whole batch - do { - v1 = v++; - const uint32_t cc = v0->flags & v1->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderLine(c, v0, v1); - v0 = v1; - num--; - } while (num); - } - // copy back the last processed vertex - c->vc.vBuffer[0] = *v0; - c->arrays.cull = v0->flags & vertex_t::CLIP_ALL; - } while (count); -} - -void drawPrimitivesLineLoop(ogles_context_t* c, GLint first, GLsizei count) -{ - if (ggl_unlikely(count < 2)) - return; - drawPrimitivesLineStrip(c, first, count); - if (ggl_likely(count >= 3)) { - vertex_t* v0 = c->vc.vBuffer; - vertex_t* v1 = c->vc.vBuffer + 1; - c->arrays.compileElement(c, v1, first); - const uint32_t cc = v0->flags & v1->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderLine(c, v0, v1); - } -} - -void drawPrimitivesLines(ogles_context_t* c, GLint first, GLsizei count) -{ - if (ggl_unlikely(count < 2)) - return; - - // vertex cache size must be multiple of 2 - const GLsizei vcs = - ((vertex_cache_t::VERTEX_BUFFER_SIZE + - vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2; - do { - vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; - c->arrays.cull = vertex_t::CLIP_ALL; - c->arrays.compileElements(c, v, first, num); - first += num; - count -= num; - if (!c->arrays.cull) { - // quick/trivial reject of the whole batch - num -= 2; - do { - const uint32_t cc = v[0].flags & v[1].flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderLine(c, v, v+1); - v += 2; - num -= 2; - } while (num >= 0); - } - } while (count >= 2); -} - -// ---------------------------------------------------------------------------- - -static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c, - GLint first, GLsizei count, int winding) -{ - // winding == 2 : fan - // winding == 1 : strip - - if (ggl_unlikely(count < 3)) - return; - - vertex_t *v, *v0, *v1, *v2; - c->arrays.cull = vertex_t::CLIP_ALL; - c->arrays.compileElements(c, c->vc.vBuffer, first, 2); - first += 2; - count -= 2; - - // vertex cache size must be multiple of 2. This is extremely important - // because it allows us to preserve the same winding when the whole - // batch is culled. We also need 2 extra vertices in the array, because - // we always keep the two first ones. - const GLsizei vcs = - ((vertex_cache_t::VERTEX_BUFFER_SIZE + - vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2; - do { - v0 = c->vc.vBuffer + 0; - v1 = c->vc.vBuffer + 1; - v = c->vc.vBuffer + 2; - GLsizei num = count > vcs ? vcs : count; - c->arrays.compileElements(c, v, first, num); - first += num; - count -= num; - if (!c->arrays.cull) { - // quick/trivial reject of the whole batch - do { - v2 = v++; - const uint32_t cc = v0->flags & v1->flags & v2->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderTriangle(c, v0, v1, v2); - swap(((winding^=1) ? v1 : v0), v2); - num--; - } while (num); - } - if (count) { - v0 = c->vc.vBuffer + 2 + num - 2; - v1 = c->vc.vBuffer + 2 + num - 1; - if ((winding&2) == 0) { - // for strips copy back the two last compiled vertices - c->vc.vBuffer[0] = *v0; - } - c->vc.vBuffer[1] = *v1; - c->arrays.cull = v0->flags & v1->flags & vertex_t::CLIP_ALL; - } - } while (count > 0); -} - -void drawPrimitivesTriangleStrip(ogles_context_t* c, - GLint first, GLsizei count) { - drawPrimitivesTriangleFanOrStrip(c, first, count, 1); -} - -void drawPrimitivesTriangleFan(ogles_context_t* c, - GLint first, GLsizei count) { - drawPrimitivesTriangleFanOrStrip(c, first, count, 2); -} - -void drawPrimitivesTriangles(ogles_context_t* c, GLint first, GLsizei count) -{ - if (ggl_unlikely(count < 3)) - return; - - // vertex cache size must be multiple of 3 - const GLsizei vcs = - ((vertex_cache_t::VERTEX_BUFFER_SIZE + - vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3; - do { - vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; - c->arrays.cull = vertex_t::CLIP_ALL; - c->arrays.compileElements(c, v, first, num); - first += num; - count -= num; - if (!c->arrays.cull) { - // quick/trivial reject of the whole batch - num -= 3; - do { - const uint32_t cc = v[0].flags & v[1].flags & v[2].flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderTriangle(c, v, v+1, v+2); - v += 3; - num -= 3; - } while (num >= 0); - } - } while (count >= 3); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -// this looks goofy, but gcc does a great job with this... -static inline unsigned int read_index(int type, const GLvoid*& p) { - unsigned int r; - if (type) { - r = *(const GLubyte*)p; - p = (const GLubyte*)p + 1; - } else { - r = *(const GLushort*)p; - p = (const GLushort*)p + 1; - } - return r; -} - -// ---------------------------------------------------------------------------- - -void drawIndexedPrimitivesPoints(ogles_context_t* c, - GLsizei count, const GLvoid *indices) -{ - if (ggl_unlikely(count < 1)) - return; - const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); - do { - vertex_t * v = fetch_vertex(c, read_index(type, indices)); - if (ggl_likely(!(v->flags & vertex_t::CLIP_ALL))) - c->prims.renderPoint(c, v); - v->locked = 0; - count--; - } while(count); -} - -// ---------------------------------------------------------------------------- - -void drawIndexedPrimitivesLineStrip(ogles_context_t* c, - GLsizei count, const GLvoid *indices) -{ - if (ggl_unlikely(count < 2)) - return; - - vertex_t * const v = c->vc.vBuffer; - vertex_t* v0 = v; - vertex_t* v1; - - const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); - c->arrays.compileElement(c, v0, read_index(type, indices)); - count -= 1; - do { - v1 = fetch_vertex(c, read_index(type, indices)); - const uint32_t cc = v0->flags & v1->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderLine(c, v0, v1); - v0->locked = 0; - v0 = v1; - count--; - } while (count); - v1->locked = 0; -} - -void drawIndexedPrimitivesLineLoop(ogles_context_t* c, - GLsizei count, const GLvoid *indices) -{ - if (ggl_unlikely(count <= 2)) { - drawIndexedPrimitivesLines(c, count, indices); - return; - } - - vertex_t * const v = c->vc.vBuffer; - vertex_t* v0 = v; - vertex_t* v1; - - const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); - c->arrays.compileElement(c, v0, read_index(type, indices)); - count -= 1; - do { - v1 = fetch_vertex(c, read_index(type, indices)); - const uint32_t cc = v0->flags & v1->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderLine(c, v0, v1); - v0->locked = 0; - v0 = v1; - count--; - } while (count); - v1->locked = 0; - - v1 = c->vc.vBuffer; - const uint32_t cc = v0->flags & v1->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderLine(c, v0, v1); -} - -void drawIndexedPrimitivesLines(ogles_context_t* c, - GLsizei count, const GLvoid *indices) -{ - if (ggl_unlikely(count < 2)) - return; - - count -= 2; - const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); - do { - vertex_t* const v0 = fetch_vertex(c, read_index(type, indices)); - vertex_t* const v1 = fetch_vertex(c, read_index(type, indices)); - const uint32_t cc = v0->flags & v1->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderLine(c, v0, v1); - v0->locked = 0; - v1->locked = 0; - count -= 2; - } while (count >= 0); -} - -// ---------------------------------------------------------------------------- - -static void drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t* c, - GLsizei count, const GLvoid *indices, int winding) -{ - // winding == 2 : fan - // winding == 1 : strip - - if (ggl_unlikely(count < 3)) - return; - - vertex_t * const v = c->vc.vBuffer; - vertex_t* v0 = v; - vertex_t* v1 = v+1; - vertex_t* v2; - - const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); - c->arrays.compileElement(c, v0, read_index(type, indices)); - c->arrays.compileElement(c, v1, read_index(type, indices)); - count -= 2; - - // note: GCC 4.1.1 here makes a prety interesting optimization - // where it duplicates the loop below based on c->arrays.indicesType - - do { - v2 = fetch_vertex(c, read_index(type, indices)); - const uint32_t cc = v0->flags & v1->flags & v2->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderTriangle(c, v0, v1, v2); - vertex_t* & consumed = ((winding^=1) ? v1 : v0); - consumed->locked = 0; - consumed = v2; - count--; - } while (count); - v0->locked = v1->locked = 0; - v2->locked = 0; -} - -void drawIndexedPrimitivesTriangleStrip(ogles_context_t* c, - GLsizei count, const GLvoid *indices) { - drawIndexedPrimitivesTriangleFanOrStrip(c, count, indices, 1); -} - -void drawIndexedPrimitivesTriangleFan(ogles_context_t* c, - GLsizei count, const GLvoid *indices) { - drawIndexedPrimitivesTriangleFanOrStrip(c, count, indices, 2); -} - -void drawIndexedPrimitivesTriangles(ogles_context_t* c, - GLsizei count, const GLvoid *indices) -{ - if (ggl_unlikely(count < 3)) - return; - - count -= 3; - if (ggl_likely(c->arrays.indicesType == GL_UNSIGNED_SHORT)) { - // This case is probably our most common case... - uint16_t const * p = (uint16_t const *)indices; - do { - vertex_t* const v0 = fetch_vertex(c, *p++); - vertex_t* const v1 = fetch_vertex(c, *p++); - vertex_t* const v2 = fetch_vertex(c, *p++); - const uint32_t cc = v0->flags & v1->flags & v2->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderTriangle(c, v0, v1, v2); - v0->locked = 0; - v1->locked = 0; - v2->locked = 0; - count -= 3; - } while (count >= 0); - } else { - uint8_t const * p = (uint8_t const *)indices; - do { - vertex_t* const v0 = fetch_vertex(c, *p++); - vertex_t* const v1 = fetch_vertex(c, *p++); - vertex_t* const v2 = fetch_vertex(c, *p++); - const uint32_t cc = v0->flags & v1->flags & v2->flags; - if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) - c->prims.renderTriangle(c, v0, v1, v2); - v0->locked = 0; - v1->locked = 0; - v2->locked = 0; - count -= 3; - } while (count >= 0); - } -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Array compilers -#endif - -void compileElement__generic(ogles_context_t* c, - vertex_t* v, GLint first) -{ - v->flags = 0; - v->index = first; - first &= vertex_cache_t::INDEX_MASK; - const GLubyte* vp = c->arrays.vertex.element(first); - c->arrays.vertex.fetch(c, v->obj.v, vp); - c->arrays.mvp_transform(&c->transforms.mvp, &v->clip, &v->obj); - c->arrays.perspective(c, v); -} - -void compileElements__generic(ogles_context_t* c, - vertex_t* v, GLint first, GLsizei count) -{ - const GLubyte* vp = c->arrays.vertex.element( - first & vertex_cache_t::INDEX_MASK); - const size_t stride = c->arrays.vertex.stride; - transform_t const* const mvp = &c->transforms.mvp; - do { - v->flags = 0; - v->index = first++; - c->arrays.vertex.fetch(c, v->obj.v, vp); - c->arrays.mvp_transform(mvp, &v->clip, &v->obj); - c->arrays.perspective(c, v); - vp += stride; - v++; - } while (--count); -} - -/* -void compileElements__3x_full(ogles_context_t* c, - vertex_t* v, GLint first, GLsizei count) -{ - const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first); - const size_t stride = c->arrays.vertex.stride / 4; -// const GLfixed* const& m = c->transforms.mvp.matrix.m; - - GLfixed m[16]; - memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m)); - - do { - const GLfixed rx = vp[0]; - const GLfixed ry = vp[1]; - const GLfixed rz = vp[2]; - vp += stride; - v->index = first++; - v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); - v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]); - v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]); - v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]); - - const GLfixed w = v->clip.w; - uint32_t clip = 0; - if (v->clip.x < -w) clip |= vertex_t::CLIP_L; - if (v->clip.x > w) clip |= vertex_t::CLIP_R; - if (v->clip.y < -w) clip |= vertex_t::CLIP_B; - if (v->clip.y > w) clip |= vertex_t::CLIP_T; - if (v->clip.z < -w) clip |= vertex_t::CLIP_N; - if (v->clip.z > w) clip |= vertex_t::CLIP_F; - v->flags = clip; - c->arrays.cull &= clip; - - //c->arrays.perspective(c, v); - v++; - } while (--count); -} -*/ - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark clippers -#endif - -static void clipVec4(vec4_t& nv, - GLfixed t, const vec4_t& s, const vec4_t& p) -{ - for (int i=0; i<4 ; i++) - nv.v[i] = gglMulAddx(t, s.v[i] - p.v[i], p.v[i], 28); -} - -static void clipVertex(ogles_context_t* c, vertex_t* nv, - GLfixed t, const vertex_t* s, const vertex_t* p) -{ - clipVec4(nv->clip, t, s->clip, p->clip); - nv->fog = gglMulAddx(t, s->fog - p->fog, p->fog, 28); - ogles_vertex_project(c, nv); - nv->flags |= vertex_t::LIT | vertex_t::EYE | vertex_t::TT; - nv->flags &= ~vertex_t::CLIP_ALL; -} - -static void clipVertexC(ogles_context_t* c, vertex_t* nv, - GLfixed t, const vertex_t* s, const vertex_t* p) -{ - clipVec4(nv->color, t, s->color, p->color); - clipVertex(c, nv, t, s, p); -} - -static void clipVertexT(ogles_context_t* c, vertex_t* nv, - GLfixed t, const vertex_t* s, const vertex_t* p) -{ - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - if (c->rasterizer.state.texture[i].enable) - clipVec4(nv->texture[i], t, s->texture[i], p->texture[i]); - } - clipVertex(c, nv, t, s, p); -} - -static void clipVertexAll(ogles_context_t* c, vertex_t* nv, - GLfixed t, const vertex_t* s, const vertex_t* p) -{ - clipVec4(nv->color, t, s->color, p->color); - clipVertexT(c, nv, t, s, p); -} - -static void clipEye(ogles_context_t* c, vertex_t* nv, - GLfixed t, const vertex_t* s, const vertex_t* p) -{ - nv->clear(); - c->arrays.clipVertex(c, nv, t, p, s); - clipVec4(nv->eye, t, s->eye, p->eye); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -void validate_arrays(ogles_context_t* c, GLenum mode) -{ - uint32_t enables = c->rasterizer.state.enables; - - // Perspective correction is not need if Ortho transform, but - // the user can still provide the w coordinate manually, so we can't - // automatically turn it off (in fact we could when the 4th coordinate - // is not spcified in the vertex array). - // W interpolation is never needed for points. - GLboolean perspective = - c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS); - c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective); - - // set anti-aliasing - GLboolean smooth = GL_FALSE; - switch (mode) { - case GL_POINTS: - smooth = c->point.smooth; - break; - case GL_LINES: - case GL_LINE_LOOP: - case GL_LINE_STRIP: - smooth = c->line.smooth; - break; - } - if (((enables & GGL_ENABLE_AA)?1:0) != smooth) - c->rasterizer.procs.enableDisable(c, GGL_AA, smooth); - - // set the shade model for this primitive - c->rasterizer.procs.shadeModel(c, - (mode == GL_POINTS) ? GL_FLAT : c->lighting.shadeModel); - - // compute all the matrices we'll need... - uint32_t want = - transform_state_t::MVP | - transform_state_t::VIEWPORT; - if (c->lighting.enable) { // needs normal transforms and eye coords - want |= transform_state_t::MVUI; - want |= transform_state_t::MODELVIEW; - } - if (enables & GGL_ENABLE_TMUS) { // needs texture transforms - want |= transform_state_t::TEXTURE; - } - if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { - want |= transform_state_t::MODELVIEW; // needs eye coords - } - ogles_validate_transform(c, want); - - // textures... - if (enables & GGL_ENABLE_TMUS) - ogles_validate_texture(c); - - // vertex compilers - c->arrays.compileElement = compileElement__generic; - c->arrays.compileElements = compileElements__generic; - - // vertex transform - c->arrays.mvp_transform = - c->transforms.mvp.pointv[c->arrays.vertex.size - 2]; - - c->arrays.mv_transform = - c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2]; - - /* - * *********************************************************************** - * pick fetchers - * *********************************************************************** - */ - - array_machine_t& am = c->arrays; - am.vertex.fetch = fetchNop; - am.normal.fetch = currentNormal; - am.color.fetch = currentColor; - - if (am.vertex.enable) { - am.vertex.resolve(); - if (am.vertex.bo || am.vertex.pointer) { - am.vertex.fetch = vertex_fct[am.vertex.size-2][am.vertex.type & 0xF]; - } - } - - if (am.normal.enable) { - am.normal.resolve(); - if (am.normal.bo || am.normal.pointer) { - am.normal.fetch = normal_fct[am.normal.size-3][am.normal.type & 0xF]; - } - } - - if (am.color.enable) { - am.color.resolve(); - if (c->lighting.enable) { - if (am.color.bo || am.color.pointer) { - am.color.fetch = color_fct[am.color.size-3][am.color.type & 0xF]; - } - } else { - if (am.color.bo || am.color.pointer) { - am.color.fetch = color_clamp_fct[am.color.size-3][am.color.type & 0xF]; - } - } - } - - int activeTmuCount = 0; - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - am.texture[i].fetch = currentTexCoord; - if (c->rasterizer.state.texture[i].enable) { - - // texture fetchers... - if (am.texture[i].enable) { - am.texture[i].resolve(); - if (am.texture[i].bo || am.texture[i].pointer) { - am.texture[i].fetch = texture_fct[am.texture[i].size-2][am.texture[i].type & 0xF]; - } - } - - // texture transform... - const int index = c->arrays.texture[i].size - 2; - c->arrays.tex_transform[i] = - c->transforms.texture[i].transform.pointv[index]; - - am.tmu = i; - activeTmuCount++; - } - } - - // pick the vertex-clipper - uint32_t clipper = 0; - // we must reload 'enables' here - enables = c->rasterizer.state.enables; - if (enables & GGL_ENABLE_SMOOTH) - clipper |= 1; // we need to interpolate colors - if (enables & GGL_ENABLE_TMUS) - clipper |= 2; // we need to interpolate textures - switch (clipper) { - case 0: c->arrays.clipVertex = clipVertex; break; - case 1: c->arrays.clipVertex = clipVertexC; break; - case 2: c->arrays.clipVertex = clipVertexT; break; - case 3: c->arrays.clipVertex = clipVertexAll; break; - } - c->arrays.clipEye = clipEye; - - // pick the primitive rasterizer - ogles_validate_primitives(c); -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- - -using namespace android; - -#if 0 -#pragma mark - -#pragma mark array API -#endif - -void glVertexPointer( - GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - ogles_context_t* c = ogles_context_t::get(); - if (size<2 || size>4 || stride<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - switch (type) { - case GL_BYTE: - case GL_SHORT: - case GL_FIXED: - case GL_FLOAT: - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - c->arrays.vertex.init(size, type, stride, pointer, c->arrays.array_buffer, 0); -} - -void glColorPointer( - GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - ogles_context_t* c = ogles_context_t::get(); - // in theory ogles doesn't allow color arrays of size 3 - // but it is very useful to 'visualize' the normal array. - if (size<3 || size>4 || stride<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - switch (type) { - case GL_UNSIGNED_BYTE: - case GL_FIXED: - case GL_FLOAT: - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - c->arrays.color.init(size, type, stride, pointer, c->arrays.array_buffer, 0); -} - -void glNormalPointer( - GLenum type, GLsizei stride, const GLvoid *pointer) -{ - ogles_context_t* c = ogles_context_t::get(); - if (stride<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - switch (type) { - case GL_BYTE: - case GL_SHORT: - case GL_FIXED: - case GL_FLOAT: - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - c->arrays.normal.init(3, type, stride, pointer, c->arrays.array_buffer, 0); -} - -void glTexCoordPointer( - GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - ogles_context_t* c = ogles_context_t::get(); - if (size<2 || size>4 || stride<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - switch (type) { - case GL_BYTE: - case GL_SHORT: - case GL_FIXED: - case GL_FLOAT: - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - const int tmu = c->arrays.activeTexture; - c->arrays.texture[tmu].init(size, type, stride, pointer, - c->arrays.array_buffer, 0); -} - - -void glEnableClientState(GLenum array) { - ogles_context_t* c = ogles_context_t::get(); - enableDisableClientState(c, array, true); -} - -void glDisableClientState(GLenum array) { - ogles_context_t* c = ogles_context_t::get(); - enableDisableClientState(c, array, false); -} - -void glClientActiveTexture(GLenum texture) -{ - ogles_context_t* c = ogles_context_t::get(); - if (texture<GL_TEXTURE0 || texture>=GL_TEXTURE0+GGL_TEXTURE_UNIT_COUNT) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - c->arrays.activeTexture = texture - GL_TEXTURE0; -} - -void glDrawArrays(GLenum mode, GLint first, GLsizei count) -{ - ogles_context_t* c = ogles_context_t::get(); - if (count<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - switch (mode) { - case GL_POINTS: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - case GL_LINES: - case GL_TRIANGLE_STRIP: - case GL_TRIANGLE_FAN: - case GL_TRIANGLES: - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - - if (count == 0 || !c->arrays.vertex.enable) - return; - if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK)) - return; // all triangles are culled - - validate_arrays(c, mode); - drawArraysPrims[mode](c, first, count); - -#if VC_CACHE_STATISTICS - c->vc.total = count; - c->vc.dump_stats(mode); -#endif -} - -void glDrawElements( - GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) -{ - ogles_context_t* c = ogles_context_t::get(); - if (count<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - switch (mode) { - case GL_POINTS: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - case GL_LINES: - case GL_TRIANGLE_STRIP: - case GL_TRIANGLE_FAN: - case GL_TRIANGLES: - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - switch (type) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - c->arrays.indicesType = type; - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (count == 0 || !c->arrays.vertex.enable) - return; - if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK)) - return; // all triangles are culled - - // clear the vertex-cache - c->vc.clear(); - validate_arrays(c, mode); - - // if indices are in a buffer object, the pointer is treated as an - // offset in that buffer. - if (c->arrays.element_array_buffer) { - indices = c->arrays.element_array_buffer->data + uintptr_t(indices); - } - - drawElementsPrims[mode](c, count, indices); - -#if VC_CACHE_STATISTICS - c->vc.total = count; - c->vc.dump_stats(mode); -#endif -} - -// ---------------------------------------------------------------------------- -// buffers -// ---------------------------------------------------------------------------- - -void glBindBuffer(GLenum target, GLuint buffer) -{ - ogles_context_t* c = ogles_context_t::get(); - if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - // create a buffer object, or bind an existing one - buffer_t const* bo = 0; - if (buffer) { - bo = c->bufferObjectManager->bind(buffer); - if (!bo) { - ogles_error(c, GL_OUT_OF_MEMORY); - return; - } - } - ((target == GL_ARRAY_BUFFER) ? - c->arrays.array_buffer : c->arrays.element_array_buffer) = bo; -} - -void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) -{ - ogles_context_t* c = ogles_context_t::get(); - if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (size<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - if ((usage!=GL_STATIC_DRAW) && (usage!=GL_DYNAMIC_DRAW)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? - c->arrays.array_buffer : c->arrays.element_array_buffer); - - if (bo == 0) { - // can't modify buffer 0 - ogles_error(c, GL_INVALID_OPERATION); - return; - } - - buffer_t* edit_bo = const_cast<buffer_t*>(bo); - if (c->bufferObjectManager->allocateStore(edit_bo, size, usage) != 0) { - ogles_error(c, GL_OUT_OF_MEMORY); - return; - } - if (data) { - memcpy(bo->data, data, size); - } -} - -void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) -{ - ogles_context_t* c = ogles_context_t::get(); - if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (offset<0 || size<0 || data==0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? - c->arrays.array_buffer : c->arrays.element_array_buffer); - - if (bo == 0) { - // can't modify buffer 0 - ogles_error(c, GL_INVALID_OPERATION); - return; - } - if (offset+size > bo->size) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - memcpy(bo->data + offset, data, size); -} - -void glDeleteBuffers(GLsizei n, const GLuint* buffers) -{ - ogles_context_t* c = ogles_context_t::get(); - if (n<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - - for (int i=0 ; i<n ; i++) { - GLuint name = buffers[i]; - if (name) { - // unbind bound deleted buffers... - if (c->arrays.element_array_buffer->name == name) { - c->arrays.element_array_buffer = 0; - } - if (c->arrays.array_buffer->name == name) { - c->arrays.array_buffer = 0; - } - if (c->arrays.vertex.bo->name == name) { - c->arrays.vertex.bo = 0; - } - if (c->arrays.normal.bo->name == name) { - c->arrays.normal.bo = 0; - } - if (c->arrays.color.bo->name == name) { - c->arrays.color.bo = 0; - } - for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) { - if (c->arrays.texture[t].bo->name == name) { - c->arrays.texture[t].bo = 0; - } - } - } - } - c->bufferObjectManager->deleteBuffers(n, buffers); - c->bufferObjectManager->recycleTokens(n, buffers); -} - -void glGenBuffers(GLsizei n, GLuint* buffers) -{ - ogles_context_t* c = ogles_context_t::get(); - if (n<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - c->bufferObjectManager->getToken(n, buffers); -} |