diff options
| author | 2019-08-23 18:14:00 +0000 | |
|---|---|---|
| committer | 2019-08-23 18:14:00 +0000 | |
| commit | 6b6168ab973b0e3c33e94e94fd4e6a440cef40e0 (patch) | |
| tree | d1dde4830e58e7254ddb0ccd7d592d2b3d60d3f0 /opengl/libagl/texture.cpp | |
| parent | 194e1069a4bf40e670db59741d0fe38fcc384071 (diff) | |
| parent | b856aff7430b57f5d32436ecb4e4d232d37723ed (diff) | |
Merge changes from topic "libagl"
* changes:
  Remove mention of legacy software renderer
  Nuke libagl and setEmulatorGlesValue
Diffstat (limited to 'opengl/libagl/texture.cpp')
| -rw-r--r-- | opengl/libagl/texture.cpp | 1643 | 
1 files changed, 0 insertions, 1643 deletions
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp deleted file mode 100644 index 4c5f3e93d3..0000000000 --- a/opengl/libagl/texture.cpp +++ /dev/null @@ -1,1643 +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" - -#include <ETC1/etc1.h> - -#include <ui/GraphicBufferMapper.h> -#include <ui/Rect.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(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 the active textures are EGLImage, they need to be locked before - * they can be used. - * - * FIXME: code below is far from being optimal - * - */ - -void ogles_lock_textures(ogles_context_t* c) -{ -    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { -        if (c->rasterizer.state.texture[i].enable) { -            texture_unit_t& u(c->textures.tmu[i]); -            ANativeWindowBuffer* native_buffer = u.texture->buffer; -            if (native_buffer) { -                c->rasterizer.procs.activeTexture(c, i); - -                auto& mapper = GraphicBufferMapper::get(); -                void* vaddr; -                mapper.lock(native_buffer->handle, GRALLOC_USAGE_SW_READ_OFTEN, -                        Rect(native_buffer->width, native_buffer->height), -                        &vaddr); - -                u.texture->setImageBits(vaddr); -                c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); -            } -        } -    } -} - -void ogles_unlock_textures(ogles_context_t* c) -{ -    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { -        if (c->rasterizer.state.texture[i].enable) { -            texture_unit_t& u(c->textures.tmu[i]); -            ANativeWindowBuffer* native_buffer = u.texture->buffer; -            if (native_buffer) { -                c->rasterizer.procs.activeTexture(c, i); - -                auto& mapper = GraphicBufferMapper::get(); -                mapper.unlock(native_buffer->handle); - -                u.texture->setImageBits(NULL); -                c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); -            } -        } -    } -    c->rasterizer.procs.activeTexture(c, c->textures.active); -} - -// ---------------------------------------------------------------------------- -#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) -{ -    // 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 GLsizei dataSizePalette4(int numLevels, int width, int height, 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; -    } - -    size_t size = (1 << indexBits) * entrySize; // palette size - -    for (int i=0 ; i< numLevels ; i++) { -        int w = (width  >> i) ? : 1; -        int h = (height >> i) ? : 1; -        int levelSize = h * ((w * indexBits) / 8) ? : 1; -        size += levelSize; -    } - -    return size; -} - -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, GGLfixed 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>=0x10000)    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 && target != GL_TEXTURE_EXTERNAL_OES) { -        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 drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, -        ogles_context_t* c) -{ -    ogles_lock_textures(c); - -    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); - -    ogles_unlock_textures(c); -} - -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; - -    drawTexxOESImp(x, y, z, w, h, c); -} - -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; -            } - -            ogles_lock_textures(c); - -            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, gglIntToFixed(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); - -            ogles_unlock_textures(c); - -            return; -        } -    } - -slow_case: -    drawTexxOESImp( -            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 && target != GL_TEXTURE_EXTERNAL_OES) { -        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 != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) { -        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: -        texParameterx(target, pname, GLfixed(params[0]), c); -        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); -} - -void glTexParameteri( -        GLenum target, GLenum pname, GLint param) -{ -    ogles_context_t* c = ogles_context_t::get(); -    texParameterx(target, pname, GLfixed(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 (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; -#ifdef GL_OES_compressed_ETC1_RGB8_texture -    case GL_ETC1_RGB8_OES: -        format      = GL_RGB; -        type        = GL_UNSIGNED_BYTE; -        break; -#endif -    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; - -#ifdef GL_OES_compressed_ETC1_RGB8_texture -    if (internalformat == GL_ETC1_RGB8_OES) { -        GLsizei compressedSize = etc1_get_encoded_data_size(width, height); -        if (compressedSize > imageSize) { -            ogles_error(c, GL_INVALID_VALUE); -            return; -        } -        int error = createTextureSurface(c, &surface, &size, -                level, format, type, width, height); -        if (error) { -            ogles_error(c, error); -            return; -        } -        if (etc1_decode_image( -                (const etc1_byte*)data, -                (etc1_byte*)surface->data, -                width, height, 3, surface->stride*3) != 0) { -            ogles_error(c, GL_INVALID_OPERATION); -        } -        return; -    } -#endif - -    // all mipmap levels are specified at once. -    const int numLevels = level<0 ? -level : 1; - -    if (dataSizePalette4(numLevels, width, height, format) > imageSize) { -        ogles_error(c, GL_INVALID_VALUE); -        return; -    } - -    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) { -        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 != (GLenum)internalformat) { -        ogles_error(c, GL_INVALID_OPERATION); -        return; -    } -    if (validFormatType(c, format, type)) { -        return; -    } - -    int32_t size = 0; -    GGLSurface* surface = 0; -    int error = createTextureSurface(c, &surface, &size, -            level, format, type, width, height); -    if (error) { -        ogles_error(c, error); -        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 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, 0, 0, userSurface, 0, 0, width, height); -        if (err) { -            ogles_error(c, err); -            return; -        } -        generateMipmap(c, level); -    } -} - -// ---------------------------------------------------------------------------- - -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 (format != 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; -    } -    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 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); - -    /* The GLES spec says: -     * If any of the pixels within the specified rectangle are outside -     * the framebuffer associated with the current rendering context, -     * then the values obtained for those pixels are undefined. -     */ -    if (x+width > GLint(cbSurface.width)) -        width = cbSurface.width - x; - -    if (y+height > GLint(cbSurface.height)) -        height = cbSurface.height - y; - -    int err = copyPixels(c, -            txSurface, 0, 0, -            cbSurface, x, y, width, 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); - -    /* The GLES spec says: -     * If any of the pixels within the specified rectangle are outside -     * the framebuffer associated with the current rendering context, -     * then the values obtained for those pixels are undefined. -     */ -    if (x+width > GLint(cbSurface.width)) -        width = cbSurface.width - x; - -    if (y+height > GLint(cbSurface.height)) -        height = cbSurface.height - y; - -    int err = copyPixels(c, -            txSurface, 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 || y<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); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark EGL Image Extension -#endif - -void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) -{ -    ogles_context_t* c = ogles_context_t::get(); -    if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) { -        ogles_error(c, GL_INVALID_ENUM); -        return; -    } - -    if (image == EGL_NO_IMAGE_KHR) { -        ogles_error(c, GL_INVALID_VALUE); -        return; -    } - -    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)image; -    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) { -        ogles_error(c, GL_INVALID_VALUE); -        return; -    } -    if (native_buffer->common.version != sizeof(ANativeWindowBuffer)) { -        ogles_error(c, GL_INVALID_VALUE); -        return; -    } - -    // bind it to the texture unit -    sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); -    tex->setImage(native_buffer); -} - -void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) -{ -    ogles_context_t* c = ogles_context_t::get(); -    if (target != GL_RENDERBUFFER_OES) { -        ogles_error(c, GL_INVALID_ENUM); -        return; -    } - -    if (image == EGL_NO_IMAGE_KHR) { -        ogles_error(c, GL_INVALID_VALUE); -        return; -    } - -    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)image; -    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) { -        ogles_error(c, GL_INVALID_VALUE); -        return; -    } -    if (native_buffer->common.version != sizeof(ANativeWindowBuffer)) { -        ogles_error(c, GL_INVALID_VALUE); -        return; -    } - -    // well, we're not supporting this extension anyways -}  |