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 | d5193d9394c5e58176d7bcdf50ef017f8a3b9e1e (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /opengl/libagl/texture.cpp | |
parent | 43aa2b1cbf7a03e248e10f4d0fec0463257cd52d (diff) | |
download | frameworks_native-d5193d9394c5e58176d7bcdf50ef017f8a3b9e1e.zip frameworks_native-d5193d9394c5e58176d7bcdf50ef017f8a3b9e1e.tar.gz frameworks_native-d5193d9394c5e58176d7bcdf50ef017f8a3b9e1e.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'opengl/libagl/texture.cpp')
-rw-r--r-- | opengl/libagl/texture.cpp | 1421 |
1 files changed, 0 insertions, 1421 deletions
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp deleted file mode 100644 index b6f534b..0000000 --- a/opengl/libagl/texture.cpp +++ /dev/null @@ -1,1421 +0,0 @@ -/* libs/opengles/texture.cpp -** -** 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 <stdio.h> -#include <stdlib.h> -#include "context.h" -#include "fp.h" -#include "state.h" -#include "texture.h" -#include "TextureObjectManager.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -static void bindTextureTmu( - ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex); - -static __attribute__((noinline)) -void generateMipmap(ogles_context_t* c, GLint level); - -// ---------------------------------------------------------------------------- - -#if 0 -#pragma mark - -#pragma mark Init -#endif - -void ogles_init_texture(ogles_context_t* c) -{ - c->textures.packAlignment = 4; - c->textures.unpackAlignment = 4; - - // each context has a default named (0) texture (not shared) - c->textures.defaultTexture = new EGLTextureObject(); - c->textures.defaultTexture->incStrong(c); - - // bind the default texture to each texture unit - for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - bindTextureTmu(c, i, 0, c->textures.defaultTexture); - memset(c->current.texture[i].v, 0, sizeof(vec4_t)); - c->current.texture[i].Q = 0x10000; - } -} - -void ogles_uninit_texture(ogles_context_t* c) -{ - if (c->textures.ggl) - gglUninit(c->textures.ggl); - c->textures.defaultTexture->decStrong(c); - for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - if (c->textures.tmu[i].texture) - c->textures.tmu[i].texture->decStrong(c); - } -} - -static __attribute__((noinline)) -void validate_tmu(ogles_context_t* c, int i) -{ - texture_unit_t& u(c->textures.tmu[i]); - if (u.dirty) { - u.dirty = 0; - c->rasterizer.procs.activeTexture(c, i); - c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); - c->rasterizer.procs.texGeni(c, GGL_S, - GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); - c->rasterizer.procs.texGeni(c, GGL_T, - GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); - c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, - GGL_TEXTURE_WRAP_S, u.texture->wraps); - c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, - GGL_TEXTURE_WRAP_T, u.texture->wrapt); - c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, - GGL_TEXTURE_MIN_FILTER, u.texture->min_filter); - c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, - GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter); - - // disable this texture unit if it's not complete - if (!u.texture->isComplete()) { - c->rasterizer.procs.disable(c, GGL_TEXTURE_2D); - } - } -} - -void ogles_validate_texture_impl(ogles_context_t* c) -{ - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - if (c->rasterizer.state.texture[i].enable) - validate_tmu(c, i); - } - c->rasterizer.procs.activeTexture(c, c->textures.active); -} - -static -void invalidate_texture(ogles_context_t* c, int tmu, uint8_t flags = 0xFF) { - c->textures.tmu[tmu].dirty = flags; -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Format conversion -#endif - -static uint32_t gl2format_table[6][4] = { - // BYTE, 565, 4444, 5551 - { GGL_PIXEL_FORMAT_A_8, - 0, 0, 0 }, // GL_ALPHA - { GGL_PIXEL_FORMAT_RGB_888, - GGL_PIXEL_FORMAT_RGB_565, - 0, 0 }, // GL_RGB - { GGL_PIXEL_FORMAT_RGBA_8888, - 0, - GGL_PIXEL_FORMAT_RGBA_4444, - GGL_PIXEL_FORMAT_RGBA_5551 }, // GL_RGBA - { GGL_PIXEL_FORMAT_L_8, - 0, 0, 0 }, // GL_LUMINANCE - { GGL_PIXEL_FORMAT_LA_88, - 0, 0, 0 }, // GL_LUMINANCE_ALPHA -}; - -static int32_t convertGLPixelFormat(GLint format, GLenum type) -{ - int32_t fi = -1; - int32_t ti = -1; - switch (format) { - case GL_ALPHA: fi = 0; break; - case GL_RGB: fi = 1; break; - case GL_RGBA: fi = 2; break; - case GL_LUMINANCE: fi = 3; break; - case GL_LUMINANCE_ALPHA: fi = 4; break; - } - switch (type) { - case GL_UNSIGNED_BYTE: ti = 0; break; - case GL_UNSIGNED_SHORT_5_6_5: ti = 1; break; - case GL_UNSIGNED_SHORT_4_4_4_4: ti = 2; break; - case GL_UNSIGNED_SHORT_5_5_5_1: ti = 3; break; - } - if (fi==-1 || ti==-1) - return 0; - return gl2format_table[fi][ti]; -} - -// ---------------------------------------------------------------------------- - -static GLenum validFormatType(ogles_context_t* c, GLenum format, GLenum type) -{ - GLenum error = 0; - if (format<GL_ALPHA || format>GL_LUMINANCE_ALPHA) { - error = GL_INVALID_ENUM; - } - if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT_4_4_4_4 && - type != GL_UNSIGNED_SHORT_5_5_5_1 && type != GL_UNSIGNED_SHORT_5_6_5) { - error = GL_INVALID_ENUM; - } - if (type == GL_UNSIGNED_SHORT_5_6_5 && format != GL_RGB) { - error = GL_INVALID_OPERATION; - } - if ((type == GL_UNSIGNED_SHORT_4_4_4_4 || - type == GL_UNSIGNED_SHORT_5_5_5_1) && format != GL_RGBA) { - error = GL_INVALID_OPERATION; - } - if (error) { - ogles_error(c, error); - } - return error; -} - -// ---------------------------------------------------------------------------- - -GGLContext* getRasterizer(ogles_context_t* c) -{ - GGLContext* ggl = c->textures.ggl; - if (ggl_unlikely(!ggl)) { - // this is quite heavy the first time... - gglInit(&ggl); - if (!ggl) { - return 0; - } - GGLfixed colors[4] = { 0, 0, 0, 0x10000 }; - c->textures.ggl = ggl; - ggl->activeTexture(ggl, 0); - ggl->enable(ggl, GGL_TEXTURE_2D); - ggl->texEnvi(ggl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); - ggl->disable(ggl, GGL_DITHER); - ggl->shadeModel(ggl, GGL_FLAT); - ggl->color4xv(ggl, colors); - } - return ggl; -} - -static __attribute__((noinline)) -int copyPixels( - ogles_context_t* c, - const GGLSurface& dst, - GLint xoffset, GLint yoffset, - const GGLSurface& src, - GLint x, GLint y, GLsizei w, GLsizei h) -{ - if ((dst.format == src.format) && - (dst.stride == src.stride) && - (dst.width == src.width) && - (dst.height == src.height) && - (dst.stride > 0) && - ((x|y) == 0) && - ((xoffset|yoffset) == 0)) - { - // this is a common case... - const GGLFormat& pixelFormat(c->rasterizer.formats[src.format]); - const size_t size = src.height * src.stride * pixelFormat.size; - memcpy(dst.data, src.data, size); - return 0; - } - - // use pixel-flinger to handle all the conversions - GGLContext* ggl = getRasterizer(c); - if (!ggl) { - // the only reason this would fail is because we ran out of memory - return GL_OUT_OF_MEMORY; - } - - ggl->colorBuffer(ggl, &dst); - ggl->bindTexture(ggl, &src); - ggl->texCoord2i(ggl, x-xoffset, y-yoffset); - ggl->recti(ggl, xoffset, yoffset, xoffset+w, yoffset+h); - return 0; -} - -// ---------------------------------------------------------------------------- - -static __attribute__((noinline)) -sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c) -{ - sp<EGLTextureObject> tex; - const int active = c->textures.active; - const GLuint name = c->textures.tmu[active].name; - - // free the reference to the previously bound object - texture_unit_t& u(c->textures.tmu[active]); - if (u.texture) - u.texture->decStrong(c); - - if (name == 0) { - // 0 is our local texture object, not shared with anyone. - // But it affects all bound TMUs immediately. - // (we need to invalidate all units bound to this texture object) - tex = c->textures.defaultTexture; - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - if (c->textures.tmu[i].texture == tex.get()) - invalidate_texture(c, i); - } - } else { - // get a new texture object for that name - tex = c->surfaceManager->replaceTexture(name); - } - - // bind this texture to the current active texture unit - // and add a reference to this texture object - u.texture = tex.get(); - u.texture->incStrong(c); - u.name = name; - invalidate_texture(c, active); - return tex; -} - -void bindTextureTmu( - ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex) -{ - if (tex.get() == c->textures.tmu[tmu].texture) - return; - - // free the reference to the previously bound object - texture_unit_t& u(c->textures.tmu[tmu]); - if (u.texture) - u.texture->decStrong(c); - - // bind this texture to the current active texture unit - // and add a reference to this texture object - u.texture = tex.get(); - u.texture->incStrong(c); - u.name = texture; - invalidate_texture(c, tmu); -} - -int createTextureSurface(ogles_context_t* c, - GGLSurface** outSurface, int32_t* outSize, GLint level, - GLenum format, GLenum type, GLsizei width, GLsizei height, - GLenum compressedFormat = 0) -{ - // find out which texture is bound to the current unit - const int active = c->textures.active; - const GLuint name = c->textures.tmu[active].name; - - // convert the pixelformat to one we can handle - const int32_t formatIdx = convertGLPixelFormat(format, type); - if (formatIdx == 0) { // we don't know what to do with this - return GL_INVALID_OPERATION; - } - - // figure out the size we need as well as the stride - const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); - const int32_t align = c->textures.unpackAlignment-1; - const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; - const size_t size = bpr * height; - const int32_t stride = bpr / pixelFormat.size; - - if (level > 0) { - const int active = c->textures.active; - EGLTextureObject* tex = c->textures.tmu[active].texture; - status_t err = tex->reallocate(level, - width, height, stride, formatIdx, compressedFormat, bpr); - if (err != NO_ERROR) - return GL_OUT_OF_MEMORY; - GGLSurface& surface = tex->editMip(level); - *outSurface = &surface; - *outSize = size; - return 0; - } - - sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); - status_t err = tex->reallocate(level, - width, height, stride, formatIdx, compressedFormat, bpr); - if (err != NO_ERROR) - return GL_OUT_OF_MEMORY; - - tex->internalformat = format; - *outSurface = &tex->surface; - *outSize = size; - return 0; -} - -static void decodePalette4(const GLvoid *data, int level, int width, int height, - void *surface, int stride, int format) - -{ - int indexBits = 8; - int entrySize = 0; - switch (format) { - case GL_PALETTE4_RGB8_OES: - indexBits = 4; - /* FALLTHROUGH */ - case GL_PALETTE8_RGB8_OES: - entrySize = 3; - break; - - case GL_PALETTE4_RGBA8_OES: - indexBits = 4; - /* FALLTHROUGH */ - case GL_PALETTE8_RGBA8_OES: - entrySize = 4; - break; - - case GL_PALETTE4_R5_G6_B5_OES: - case GL_PALETTE4_RGBA4_OES: - case GL_PALETTE4_RGB5_A1_OES: - indexBits = 4; - /* FALLTHROUGH */ - case GL_PALETTE8_R5_G6_B5_OES: - case GL_PALETTE8_RGBA4_OES: - case GL_PALETTE8_RGB5_A1_OES: - entrySize = 2; - break; - } - - const int paletteSize = (1 << indexBits) * entrySize; - uint8_t const* pixels = (uint8_t *)data + paletteSize; - for (int i=0 ; i<level ; i++) { - int w = (width >> i) ? : 1; - int h = (height >> i) ? : 1; - pixels += h * ((w * indexBits) / 8); - } - width = (width >> level) ? : 1; - height = (height >> level) ? : 1; - - if (entrySize == 2) { - uint8_t const* const palette = (uint8_t*)data; - for (int y=0 ; y<height ; y++) { - uint8_t* p = (uint8_t*)surface + y*stride*2; - if (indexBits == 8) { - for (int x=0 ; x<width ; x++) { - int index = 2 * (*pixels++); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - } - } else { - for (int x=0 ; x<width ; x+=2) { - int v = *pixels++; - int index = 2 * (v >> 4); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - if (x+1 < width) { - index = 2 * (v & 0xF); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - } - } - } - } - } else if (entrySize == 3) { - uint8_t const* const palette = (uint8_t*)data; - for (int y=0 ; y<height ; y++) { - uint8_t* p = (uint8_t*)surface + y*stride*3; - if (indexBits == 8) { - for (int x=0 ; x<width ; x++) { - int index = 3 * (*pixels++); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - *p++ = palette[index + 2]; - } - } else { - for (int x=0 ; x<width ; x+=2) { - int v = *pixels++; - int index = 3 * (v >> 4); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - *p++ = palette[index + 2]; - if (x+1 < width) { - index = 3 * (v & 0xF); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - *p++ = palette[index + 2]; - } - } - } - } - } else if (entrySize == 4) { - uint8_t const* const palette = (uint8_t*)data; - for (int y=0 ; y<height ; y++) { - uint8_t* p = (uint8_t*)surface + y*stride*4; - if (indexBits == 8) { - for (int x=0 ; x<width ; x++) { - int index = 4 * (*pixels++); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - *p++ = palette[index + 2]; - *p++ = palette[index + 3]; - } - } else { - for (int x=0 ; x<width ; x+=2) { - int v = *pixels++; - int index = 4 * (v >> 4); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - *p++ = palette[index + 2]; - *p++ = palette[index + 3]; - if (x+1 < width) { - index = 4 * (v & 0xF); - *p++ = palette[index + 0]; - *p++ = palette[index + 1]; - *p++ = palette[index + 2]; - *p++ = palette[index + 3]; - } - } - } - } - } -} - - - -static __attribute__((noinline)) -void set_depth_and_fog(ogles_context_t* c, GLint z) -{ - const uint32_t enables = c->rasterizer.state.enables; - // we need to compute Zw - int32_t iterators[3]; - iterators[1] = iterators[2] = 0; - GGLfixed Zw; - GGLfixed n = gglFloatToFixed(c->transforms.vpt.zNear); - GGLfixed f = gglFloatToFixed(c->transforms.vpt.zFar); - if (z<=0) Zw = n; - else if (z>=1) Zw = f; - else Zw = gglMulAddx(z, (f-n), n); - if (enables & GGL_ENABLE_FOG) { - // set up fog if needed... - iterators[0] = c->fog.fog(c, Zw); - c->rasterizer.procs.fogGrad3xv(c, iterators); - } - if (enables & GGL_ENABLE_DEPTH_TEST) { - // set up z-test if needed... - int32_t z = (Zw & ~(Zw>>31)); - if (z >= 0x10000) - z = 0xFFFF; - iterators[0] = (z << 16) | z; - c->rasterizer.procs.zGrad3xv(c, iterators); - } -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Generate mimaps -#endif - -extern status_t buildAPyramid(ogles_context_t* c, EGLTextureObject* tex); - -void generateMipmap(ogles_context_t* c, GLint level) -{ - if (level == 0) { - const int active = c->textures.active; - EGLTextureObject* tex = c->textures.tmu[active].texture; - if (tex->generate_mipmap) { - if (buildAPyramid(c, tex) != NO_ERROR) { - ogles_error(c, GL_OUT_OF_MEMORY); - return; - } - } - } -} - - -static void texParameterx( - GLenum target, GLenum pname, GLfixed param, ogles_context_t* c) -{ - if (target != GL_TEXTURE_2D) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - - EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; - switch (pname) { - case GL_TEXTURE_WRAP_S: - if ((param == GL_REPEAT) || - (param == GL_CLAMP_TO_EDGE)) { - textureObject->wraps = param; - } else { - goto invalid_enum; - } - break; - case GL_TEXTURE_WRAP_T: - if ((param == GL_REPEAT) || - (param == GL_CLAMP_TO_EDGE)) { - textureObject->wrapt = param; - } else { - goto invalid_enum; - } - break; - case GL_TEXTURE_MIN_FILTER: - if ((param == GL_NEAREST) || - (param == GL_LINEAR) || - (param == GL_NEAREST_MIPMAP_NEAREST) || - (param == GL_LINEAR_MIPMAP_NEAREST) || - (param == GL_NEAREST_MIPMAP_LINEAR) || - (param == GL_LINEAR_MIPMAP_LINEAR)) { - textureObject->min_filter = param; - } else { - goto invalid_enum; - } - break; - case GL_TEXTURE_MAG_FILTER: - if ((param == GL_NEAREST) || - (param == GL_LINEAR)) { - textureObject->mag_filter = param; - } else { - goto invalid_enum; - } - break; - case GL_GENERATE_MIPMAP: - textureObject->generate_mipmap = param; - break; - default: -invalid_enum: - ogles_error(c, GL_INVALID_ENUM); - return; - } - invalidate_texture(c, c->textures.active); -} - - -static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, - ogles_context_t* c) -{ - // quickly reject empty rects - if ((w|h) <= 0) - return; - - const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; - y = gglIntToFixed(cbSurface.height) - (y + h); - w >>= FIXED_BITS; - h >>= FIXED_BITS; - - // set up all texture units - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - if (!c->rasterizer.state.texture[i].enable) - continue; - - int32_t texcoords[8]; - texture_unit_t& u(c->textures.tmu[i]); - - // validate this tmu (bind, wrap, filter) - validate_tmu(c, i); - // we CLAMP here, which works with premultiplied (s,t) - c->rasterizer.procs.texParameteri(c, - GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP); - c->rasterizer.procs.texParameteri(c, - GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP); - u.dirty = 0xFF; // XXX: should be more subtle - - EGLTextureObject* textureObject = u.texture; - const GLint Ucr = textureObject->crop_rect[0] << 16; - const GLint Vcr = textureObject->crop_rect[1] << 16; - const GLint Wcr = textureObject->crop_rect[2] << 16; - const GLint Hcr = textureObject->crop_rect[3] << 16; - - // computes texture coordinates (pre-multiplied) - int32_t dsdx = Wcr / w; // dsdx = ((Wcr/w)/Wt)*Wt - int32_t dtdy =-Hcr / h; // dtdy = -((Hcr/h)/Ht)*Ht - int32_t s0 = Ucr - gglMulx(dsdx, x); // s0 = Ucr - x * dsdx - int32_t t0 = (Vcr+Hcr) - gglMulx(dtdy, y); // t0 = (Vcr+Hcr) - y*dtdy - texcoords[0] = s0; - texcoords[1] = dsdx; - texcoords[2] = 0; - texcoords[3] = t0; - texcoords[4] = 0; - texcoords[5] = dtdy; - texcoords[6] = 0; - texcoords[7] = 0; - c->rasterizer.procs.texCoordGradScale8xv(c, i, texcoords); - } - - const uint32_t enables = c->rasterizer.state.enables; - if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG))) - set_depth_and_fog(c, z); - - c->rasterizer.procs.activeTexture(c, c->textures.active); - c->rasterizer.procs.color4xv(c, c->currentColorClamped.v); - c->rasterizer.procs.disable(c, GGL_W_LERP); - c->rasterizer.procs.disable(c, GGL_AA); - c->rasterizer.procs.shadeModel(c, GL_FLAT); - c->rasterizer.procs.recti(c, - gglFixedToIntRound(x), - gglFixedToIntRound(y), - gglFixedToIntRound(x)+w, - gglFixedToIntRound(y)+h); -} - -static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c) -{ - // All coordinates are integer, so if we have only one - // texture unit active and no scaling is required - // THEN, we can use our special 1:1 mapping - // which is a lot faster. - - if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) { - const int tmu = 0; - texture_unit_t& u(c->textures.tmu[tmu]); - EGLTextureObject* textureObject = u.texture; - const GLint Wcr = textureObject->crop_rect[2]; - const GLint Hcr = textureObject->crop_rect[3]; - - if ((w == Wcr) && (h == -Hcr)) { - if ((w|h) <= 0) return; // quickly reject empty rects - - if (u.dirty) { - c->rasterizer.procs.activeTexture(c, tmu); - c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); - c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, - GGL_TEXTURE_MIN_FILTER, u.texture->min_filter); - c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, - GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter); - } - c->rasterizer.procs.texGeni(c, GGL_S, - GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); - c->rasterizer.procs.texGeni(c, GGL_T, - GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); - u.dirty = 0xFF; // XXX: should be more subtle - c->rasterizer.procs.activeTexture(c, c->textures.active); - - const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; - y = cbSurface.height - (y + h); - const GLint Ucr = textureObject->crop_rect[0]; - const GLint Vcr = textureObject->crop_rect[1]; - const GLint s0 = Ucr - x; - const GLint t0 = (Vcr + Hcr) - y; - - const GLuint tw = textureObject->surface.width; - const GLuint th = textureObject->surface.height; - if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) { - // The GL spec is unclear about what should happen - // in this case, so we just use the slow case, which - // at least won't crash - goto slow_case; - } - - c->rasterizer.procs.texCoord2i(c, s0, t0); - const uint32_t enables = c->rasterizer.state.enables; - if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG))) - set_depth_and_fog(c, z); - - c->rasterizer.procs.color4xv(c, c->currentColorClamped.v); - c->rasterizer.procs.disable(c, GGL_W_LERP); - c->rasterizer.procs.disable(c, GGL_AA); - c->rasterizer.procs.shadeModel(c, GL_FLAT); - c->rasterizer.procs.recti(c, x, y, x+w, y+h); - return; - } - } - -slow_case: - drawTexxOES( - gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z), - gglIntToFixed(w), gglIntToFixed(h), - c); -} - - -}; // namespace android -// ---------------------------------------------------------------------------- - -using namespace android; - - -#if 0 -#pragma mark - -#pragma mark Texture API -#endif - -void glActiveTexture(GLenum texture) -{ - ogles_context_t* c = ogles_context_t::get(); - if (uint32_t(texture-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - c->textures.active = texture - GL_TEXTURE0; - c->rasterizer.procs.activeTexture(c, c->textures.active); -} - -void glBindTexture(GLenum target, GLuint texture) -{ - ogles_context_t* c = ogles_context_t::get(); - if (target != GL_TEXTURE_2D) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - - // Bind or create a texture - sp<EGLTextureObject> tex; - if (texture == 0) { - // 0 is our local texture object - tex = c->textures.defaultTexture; - } else { - tex = c->surfaceManager->texture(texture); - if (ggl_unlikely(tex == 0)) { - tex = c->surfaceManager->createTexture(texture); - if (tex == 0) { - ogles_error(c, GL_OUT_OF_MEMORY); - return; - } - } - } - bindTextureTmu(c, c->textures.active, texture, tex); -} - -void glGenTextures(GLsizei n, GLuint *textures) -{ - ogles_context_t* c = ogles_context_t::get(); - if (n<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - // generate unique (shared) texture names - c->surfaceManager->getToken(n, textures); -} - -void glDeleteTextures(GLsizei n, const GLuint *textures) -{ - ogles_context_t* c = ogles_context_t::get(); - if (n<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - - // If deleting a bound texture, bind this unit to 0 - for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) { - if (c->textures.tmu[t].name == 0) - continue; - for (int i=0 ; i<n ; i++) { - if (textures[i] && (textures[i] == c->textures.tmu[t].name)) { - // bind this tmu to texture 0 - sp<EGLTextureObject> tex(c->textures.defaultTexture); - bindTextureTmu(c, t, 0, tex); - } - } - } - c->surfaceManager->deleteTextures(n, textures); - c->surfaceManager->recycleTokens(n, textures); -} - -void glMultiTexCoord4f( - GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) -{ - ogles_context_t* c = ogles_context_t::get(); - if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - const int tmu = target-GL_TEXTURE0; - c->current.texture[tmu].S = gglFloatToFixed(s); - c->current.texture[tmu].T = gglFloatToFixed(t); - c->current.texture[tmu].R = gglFloatToFixed(r); - c->current.texture[tmu].Q = gglFloatToFixed(q); -} - -void glMultiTexCoord4x( - GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) -{ - ogles_context_t* c = ogles_context_t::get(); - if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - const int tmu = target-GL_TEXTURE0; - c->current.texture[tmu].S = s; - c->current.texture[tmu].T = t; - c->current.texture[tmu].R = r; - c->current.texture[tmu].Q = q; -} - -void glPixelStorei(GLenum pname, GLint param) -{ - ogles_context_t* c = ogles_context_t::get(); - if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if ((param<=0 || param>8) || (param & (param-1))) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - if (pname == GL_PACK_ALIGNMENT) - c->textures.packAlignment = param; - if (pname == GL_UNPACK_ALIGNMENT) - c->textures.unpackAlignment = param; -} - -void glTexEnvf(GLenum target, GLenum pname, GLfloat param) -{ - ogles_context_t* c = ogles_context_t::get(); - c->rasterizer.procs.texEnvi(c, target, pname, GLint(param)); -} - -void glTexEnvfv( - GLenum target, GLenum pname, const GLfloat *params) -{ - ogles_context_t* c = ogles_context_t::get(); - if (pname == GL_TEXTURE_ENV_MODE) { - c->rasterizer.procs.texEnvi(c, target, pname, GLint(*params)); - return; - } - if (pname == GL_TEXTURE_ENV_COLOR) { - GGLfixed fixed[4]; - for (int i=0 ; i<4 ; i++) - fixed[i] = gglFloatToFixed(params[i]); - c->rasterizer.procs.texEnvxv(c, target, pname, fixed); - return; - } - ogles_error(c, GL_INVALID_ENUM); -} - -void glTexEnvx(GLenum target, GLenum pname, GLfixed param) -{ - ogles_context_t* c = ogles_context_t::get(); - c->rasterizer.procs.texEnvi(c, target, pname, param); -} - -void glTexEnvxv( - GLenum target, GLenum pname, const GLfixed *params) -{ - ogles_context_t* c = ogles_context_t::get(); - c->rasterizer.procs.texEnvxv(c, target, pname, params); -} - -void glTexParameteriv( - GLenum target, GLenum pname, const GLint* params) -{ - ogles_context_t* c = ogles_context_t::get(); - if (target != GGL_TEXTURE_2D) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - - EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; - switch (pname) { - case GL_TEXTURE_CROP_RECT_OES: - memcpy(textureObject->crop_rect, params, 4*sizeof(GLint)); - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } -} - -void glTexParameterf( - GLenum target, GLenum pname, GLfloat param) -{ - ogles_context_t* c = ogles_context_t::get(); - texParameterx(target, pname, GLfixed(param), c); -} - -void glTexParameterx( - GLenum target, GLenum pname, GLfixed param) -{ - ogles_context_t* c = ogles_context_t::get(); - texParameterx(target, pname, param, c); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -void glCompressedTexImage2D( - GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLint border, - GLsizei imageSize, const GLvoid *data) -{ - ogles_context_t* c = ogles_context_t::get(); - if (target != GL_TEXTURE_2D) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if ((internalformat < GL_PALETTE4_RGB8_OES || - internalformat > GL_PALETTE8_RGB5_A1_OES)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (width<0 || height<0 || border!=0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - - // "uncompress" the texture since pixelflinger doesn't support - // any compressed texture format natively. - GLenum format; - GLenum type; - switch (internalformat) { - case GL_PALETTE8_RGB8_OES: - case GL_PALETTE4_RGB8_OES: - format = GL_RGB; - type = GL_UNSIGNED_BYTE; - break; - case GL_PALETTE8_RGBA8_OES: - case GL_PALETTE4_RGBA8_OES: - format = GL_RGBA; - type = GL_UNSIGNED_BYTE; - break; - case GL_PALETTE8_R5_G6_B5_OES: - case GL_PALETTE4_R5_G6_B5_OES: - format = GL_RGB; - type = GL_UNSIGNED_SHORT_5_6_5; - break; - case GL_PALETTE8_RGBA4_OES: - case GL_PALETTE4_RGBA4_OES: - format = GL_RGBA; - type = GL_UNSIGNED_SHORT_4_4_4_4; - break; - case GL_PALETTE8_RGB5_A1_OES: - case GL_PALETTE4_RGB5_A1_OES: - format = GL_RGBA; - type = GL_UNSIGNED_SHORT_5_5_5_1; - break; - default: - ogles_error(c, GL_INVALID_ENUM); - return; - } - - if (!data || !width || !height) { - // unclear if this is an error or not... - return; - } - - int32_t size; - GGLSurface* surface; - // all mipmap levels are specified at once. - const int numLevels = level<0 ? -level : 1; - for (int i=0 ; i<numLevels ; i++) { - int lod_w = (width >> i) ? : 1; - int lod_h = (height >> i) ? : 1; - int error = createTextureSurface(c, &surface, &size, - i, format, type, lod_w, lod_h); - if (error) { - ogles_error(c, error); - return; - } - decodePalette4(data, i, width, height, - surface->data, surface->stride, internalformat); - } -} - - -void glTexImage2D( - GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, const GLvoid *pixels) -{ - ogles_context_t* c = ogles_context_t::get(); - if (target != GL_TEXTURE_2D && target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (width<0 || height<0 || border!=0 || level < 0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - if (format != internalformat) { - ogles_error(c, GL_INVALID_OPERATION); - return; - } - if (validFormatType(c, format, type)) { - return; - } - - int32_t size = 0; - GGLSurface* surface = 0; - if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { - int error = createTextureSurface(c, &surface, &size, - level, format, type, width, height); - if (error) { - ogles_error(c, error); - return; - } - } else if (pixels == 0 || level != 0) { - // pixel can't be null for direct texture - ogles_error(c, GL_INVALID_OPERATION); - return; - } - - if (pixels) { - const int32_t formatIdx = convertGLPixelFormat(format, type); - const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); - const int32_t align = c->textures.unpackAlignment-1; - const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; - const size_t size = bpr * height; - const int32_t stride = bpr / pixelFormat.size; - - GGLSurface userSurface; - userSurface.version = sizeof(userSurface); - userSurface.width = width; - userSurface.height = height; - userSurface.stride = stride; - userSurface.format = formatIdx; - userSurface.compressedFormat = 0; - userSurface.data = (GLubyte*)pixels; - - if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { - int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); - if (err) { - ogles_error(c, err); - return; - } - generateMipmap(c, level); - } else { - // bind it to the texture unit - sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); - tex->setSurface(&userSurface); - } - } -} - -// ---------------------------------------------------------------------------- - -void glCompressedTexSubImage2D( - GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, - const GLvoid *data) -{ - ogles_context_t* c = ogles_context_t::get(); - ogles_error(c, GL_INVALID_ENUM); -} - -void glTexSubImage2D( - GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid *pixels) -{ - ogles_context_t* c = ogles_context_t::get(); - if (target != GL_TEXTURE_2D) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - if (validFormatType(c, format, type)) { - return; - } - - // find out which texture is bound to the current unit - const int active = c->textures.active; - EGLTextureObject* tex = c->textures.tmu[active].texture; - const GGLSurface& surface(tex->mip(level)); - - if (!tex->internalformat || tex->direct) { - ogles_error(c, GL_INVALID_OPERATION); - return; - } - if ((xoffset + width > GLsizei(surface.width)) || - (yoffset + height > GLsizei(surface.height))) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - if (!width || !height) { - return; // okay, but no-op. - } - - // figure out the size we need as well as the stride - const int32_t formatIdx = convertGLPixelFormat(format, type); - if (formatIdx == 0) { // we don't know what to do with this - ogles_error(c, GL_INVALID_OPERATION); - return; - } - - const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); - const int32_t align = c->textures.unpackAlignment-1; - const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; - const size_t size = bpr * height; - const int32_t stride = bpr / pixelFormat.size; - GGLSurface userSurface; - userSurface.version = sizeof(userSurface); - userSurface.width = width; - userSurface.height = height; - userSurface.stride = stride; - userSurface.format = formatIdx; - userSurface.compressedFormat = 0; - userSurface.data = (GLubyte*)pixels; - - int err = copyPixels(c, - surface, xoffset, yoffset, - userSurface, 0, 0, width, height); - if (err) { - ogles_error(c, err); - return; - } - - generateMipmap(c, level); - - // since we only changed the content of the texture, we don't need - // to call bindTexture on the main rasterizer. -} - -// ---------------------------------------------------------------------------- - -void glCopyTexImage2D( - GLenum target, GLint level, GLenum internalformat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border) -{ - ogles_context_t* c = ogles_context_t::get(); - if (target != GL_TEXTURE_2D) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (internalformat<GL_ALPHA || internalformat>GL_LUMINANCE_ALPHA) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (width<0 || height<0 || border!=0 || level<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - - GLenum format = 0; - GLenum type = GL_UNSIGNED_BYTE; - const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; - const int cbFormatIdx = cbSurface.format; - switch (cbFormatIdx) { - case GGL_PIXEL_FORMAT_RGB_565: - type = GL_UNSIGNED_SHORT_5_6_5; - break; - case GGL_PIXEL_FORMAT_RGBA_5551: - type = GL_UNSIGNED_SHORT_5_5_5_1; - break; - case GGL_PIXEL_FORMAT_RGBA_4444: - type = GL_UNSIGNED_SHORT_4_4_4_4; - break; - } - switch (internalformat) { - case GL_ALPHA: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE: - type = GL_UNSIGNED_BYTE; - break; - } - - // figure out the format to use for the new texture - switch (cbFormatIdx) { - case GGL_PIXEL_FORMAT_RGBA_8888: - case GGL_PIXEL_FORMAT_A_8: - case GGL_PIXEL_FORMAT_RGBA_5551: - case GGL_PIXEL_FORMAT_RGBA_4444: - format = internalformat; - break; - case GGL_PIXEL_FORMAT_RGBX_8888: - case GGL_PIXEL_FORMAT_RGB_888: - case GGL_PIXEL_FORMAT_RGB_565: - case GGL_PIXEL_FORMAT_L_8: - switch (internalformat) { - case GL_LUMINANCE: - case GL_RGB: - format = internalformat; - break; - } - break; - } - - if (format == 0) { - // invalid combination - ogles_error(c, GL_INVALID_ENUM); - return; - } - - // create the new texture... - int32_t size; - GGLSurface* surface; - int error = createTextureSurface(c, &surface, &size, - level, format, type, width, height); - if (error) { - ogles_error(c, error); - return; - } - - // The bottom row is stored first in textures - GGLSurface txSurface(*surface); - txSurface.stride = -txSurface.stride; - - // (x,y) is the lower-left corner of colorBuffer - y = cbSurface.height - (y + height); - - int err = copyPixels(c, - txSurface, 0, 0, - cbSurface, x, y, cbSurface.width, cbSurface.height); - if (err) { - ogles_error(c, err); - } - - generateMipmap(c, level); -} - -void glCopyTexSubImage2D( - GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLint x, GLint y, GLsizei width, GLsizei height) -{ - ogles_context_t* c = ogles_context_t::get(); - if (target != GL_TEXTURE_2D) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - if (!width || !height) { - return; // okay, but no-op. - } - - // find out which texture is bound to the current unit - const int active = c->textures.active; - EGLTextureObject* tex = c->textures.tmu[active].texture; - const GGLSurface& surface(tex->mip(level)); - - if (!tex->internalformat) { - ogles_error(c, GL_INVALID_OPERATION); - return; - } - if ((xoffset + width > GLsizei(surface.width)) || - (yoffset + height > GLsizei(surface.height))) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - - // The bottom row is stored first in textures - GGLSurface txSurface(surface); - txSurface.stride = -txSurface.stride; - - // (x,y) is the lower-left corner of colorBuffer - const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; - y = cbSurface.height - (y + height); - - int err = copyPixels(c, - surface, xoffset, yoffset, - cbSurface, x, y, width, height); - if (err) { - ogles_error(c, err); - return; - } - - generateMipmap(c, level); -} - -void glReadPixels( - GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid *pixels) -{ - ogles_context_t* c = ogles_context_t::get(); - if ((format != GL_RGBA) && (format != GL_RGB)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if ((type != GL_UNSIGNED_BYTE) && (type != GL_UNSIGNED_SHORT_5_6_5)) { - ogles_error(c, GL_INVALID_ENUM); - return; - } - if (width<0 || height<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - if (x<0 || x<0) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - - int32_t formatIdx = GGL_PIXEL_FORMAT_NONE; - if ((format == GL_RGBA) && (type == GL_UNSIGNED_BYTE)) { - formatIdx = GGL_PIXEL_FORMAT_RGBA_8888; - } else if ((format == GL_RGB) && (type == GL_UNSIGNED_SHORT_5_6_5)) { - formatIdx = GGL_PIXEL_FORMAT_RGB_565; - } else { - ogles_error(c, GL_INVALID_OPERATION); - return; - } - - const GGLSurface& readSurface = c->rasterizer.state.buffers.read.s; - if ((x+width > GLint(readSurface.width)) || - (y+height > GLint(readSurface.height))) { - ogles_error(c, GL_INVALID_VALUE); - return; - } - - const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); - const int32_t align = c->textures.packAlignment-1; - const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; - const int32_t stride = bpr / pixelFormat.size; - - GGLSurface userSurface; - userSurface.version = sizeof(userSurface); - userSurface.width = width; - userSurface.height = height; - userSurface.stride = -stride; // bottom row is transfered first - userSurface.format = formatIdx; - userSurface.compressedFormat = 0; - userSurface.data = (GLubyte*)pixels; - - // use pixel-flinger to handle all the conversions - GGLContext* ggl = getRasterizer(c); - if (!ggl) { - // the only reason this would fail is because we ran out of memory - ogles_error(c, GL_OUT_OF_MEMORY); - return; - } - - ggl->colorBuffer(ggl, &userSurface); // destination is user buffer - ggl->bindTexture(ggl, &readSurface); // source is read-buffer - ggl->texCoord2i(ggl, x, readSurface.height - (y + height)); - ggl->recti(ggl, 0, 0, width, height); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark DrawTexture Extension -#endif - -void glDrawTexsvOES(const GLshort* coords) { - ogles_context_t* c = ogles_context_t::get(); - drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); -} -void glDrawTexivOES(const GLint* coords) { - ogles_context_t* c = ogles_context_t::get(); - drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); -} -void glDrawTexsOES(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { - ogles_context_t* c = ogles_context_t::get(); - drawTexiOES(x, y, z, w, h, c); -} -void glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h) { - ogles_context_t* c = ogles_context_t::get(); - drawTexiOES(x, y, z, w, h, c); -} - -void glDrawTexfvOES(const GLfloat* coords) { - ogles_context_t* c = ogles_context_t::get(); - drawTexxOES( - gglFloatToFixed(coords[0]), - gglFloatToFixed(coords[1]), - gglFloatToFixed(coords[2]), - gglFloatToFixed(coords[3]), - gglFloatToFixed(coords[4]), - c); -} -void glDrawTexxvOES(const GLfixed* coords) { - ogles_context_t* c = ogles_context_t::get(); - drawTexxOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); -} -void glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h){ - ogles_context_t* c = ogles_context_t::get(); - drawTexxOES( - gglFloatToFixed(x), gglFloatToFixed(y), gglFloatToFixed(z), - gglFloatToFixed(w), gglFloatToFixed(h), - c); -} -void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { - ogles_context_t* c = ogles_context_t::get(); - drawTexxOES(x, y, z, w, h, c); -} |