diff options
author | David Li <davidxli@google.com> | 2011-03-01 16:54:04 -0800 |
---|---|---|
committer | David Li <davidxli@google.com> | 2011-03-08 17:41:29 -0800 |
commit | af94ceb5df8c7ee21d84a58caa5f632663d4e1b0 (patch) | |
tree | d4d71fbdd5d9119619d35a3a933f892a50124853 /opengl/libagl2/src/texture.cpp | |
parent | b57af729808cc33f470afaf266b857a3e91ca3e7 (diff) | |
download | frameworks_base-af94ceb5df8c7ee21d84a58caa5f632663d4e1b0.zip frameworks_base-af94ceb5df8c7ee21d84a58caa5f632663d4e1b0.tar.gz frameworks_base-af94ceb5df8c7ee21d84a58caa5f632663d4e1b0.tar.bz2 |
Initial commit of libAgl2 using Pixelflinger2 in external/mesa3d
Somewhat functional, refer to README for details.
Need to enable Android.mk to build.
It builds libGLES_android.so, which needs to replace
the one in system/lib/egl built by libagl.
Change-Id: Iec3aaa8f3963a4185d81955cd24019eb0c4a5850
Signed-off-by: David Li <davidxli@google.com>
Diffstat (limited to 'opengl/libagl2/src/texture.cpp')
-rw-r--r-- | opengl/libagl2/src/texture.cpp | 534 |
1 files changed, 534 insertions, 0 deletions
diff --git a/opengl/libagl2/src/texture.cpp b/opengl/libagl2/src/texture.cpp new file mode 100644 index 0000000..4de1f16 --- /dev/null +++ b/opengl/libagl2/src/texture.cpp @@ -0,0 +1,534 @@ +#include "gles2context.h" + +//#undef LOGD +//#define LOGD(...) + +#define API_ENTRY +#define CALL_GL_API(NAME,...) LOGD("?"#NAME); assert(0); +#define CALL_GL_API_RETURN(NAME,...) LOGD("?"#NAME); assert(0); return 0; + +static inline GGLTexture * AllocTexture() +{ + GGLTexture * tex = (GGLTexture *)calloc(1, sizeof(GGLTexture)); + tex->minFilter = GGLTexture::GGL_LINEAR; // should be NEAREST_ MIPMAP_LINEAR + tex->magFilter = GGLTexture::GGL_LINEAR; + return tex; +} + +void GLES2Context::InitializeTextures() +{ + tex.textures = std::map<GLuint, GGLTexture *>(); // the entire struct has been zeroed in constructor + tex.tex2D = AllocTexture(); + tex.textures[GL_TEXTURE_2D] = tex.tex2D; + tex.texCube = AllocTexture(); + tex.textures[GL_TEXTURE_CUBE_MAP] = tex.texCube; + for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) { + tex.tmus[i] = NULL; + tex.sampler2tmu[i] = NULL; + } + + tex.active = 0; + + tex.free = max(GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP) + 1; + + tex.tex2D->format = GGL_PIXEL_FORMAT_RGBA_8888; + tex.tex2D->type = GL_TEXTURE_2D; + tex.tex2D->levelCount = 1; + tex.tex2D->wrapS = tex.tex2D->wrapT = GGLTexture::GGL_REPEAT; + tex.tex2D->minFilter = tex.tex2D->magFilter = GGLTexture::GGL_NEAREST; + tex.tex2D->width = tex.tex2D->height = 1; + tex.tex2D->levels = malloc(4); + *(unsigned *)tex.tex2D->levels = 0xff000000; + + + tex.texCube->format = GGL_PIXEL_FORMAT_RGBA_8888; + tex.texCube->type = GL_TEXTURE_CUBE_MAP; + tex.texCube->levelCount = 1; + tex.texCube->wrapS = tex.texCube->wrapT = GGLTexture::GGL_REPEAT; + tex.texCube->minFilter = tex.texCube->magFilter = GGLTexture::GGL_NEAREST; + tex.texCube->width = tex.texCube->height = 1; + tex.texCube->levels = malloc(4 * 6); + static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000, + 0xff00ffff, 0xffffff00, 0xffff00ff + }; + memcpy(tex.texCube->levels, texels, sizeof texels); + + //texture.levelCount = GenerateMipmaps(texture.levels, texture.width, texture.height); + + // static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000, + // 0xff00ffff, 0xffffff00, 0xffff00ff}; + // memcpy(texture.levels[0], texels, sizeof texels); + // texture.format = GGL_PIXEL_FORMAT_RGBA_8888; + // texture.width = texture.height = 1; + //texture.height /= 6; + //texture.type = GL_TEXTURE_CUBE_MAP; + + tex.unpack = 4; +} + +void GLES2Context::TextureState::UpdateSampler(GGLInterface * iface, unsigned tmu) +{ + for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) + if (tmu == sampler2tmu[i]) + iface->SetSampler(iface, i, tmus[tmu]); +} + +void GLES2Context::UninitializeTextures() +{ + for (std::map<GLuint, GGLTexture *>::iterator it = tex.textures.begin(); it != tex.textures.end(); it++) { + if (!it->second) + continue; + free(it->second->levels); + free(it->second); + } +} + +static inline void GetFormatAndBytesPerPixel(const GLenum format, unsigned * bytesPerPixel, + GGLPixelFormat * texFormat) +{ + switch (format) { + case GL_ALPHA: + *texFormat = GGL_PIXEL_FORMAT_A_8; + *bytesPerPixel = 1; + break; + case GL_LUMINANCE: + *texFormat = GGL_PIXEL_FORMAT_L_8; + *bytesPerPixel = 1; + break; + case GL_LUMINANCE_ALPHA: + *texFormat = GGL_PIXEL_FORMAT_LA_88; + *bytesPerPixel = 2; + break; + case GL_RGB: + *texFormat = GGL_PIXEL_FORMAT_RGB_888; + *bytesPerPixel = 3; + break; + case GL_RGBA: + *texFormat = GGL_PIXEL_FORMAT_RGBA_8888; + *bytesPerPixel = 4; + break; + + // internal formats to avoid conversion + case GL_UNSIGNED_SHORT_5_6_5: + *texFormat = GGL_PIXEL_FORMAT_RGB_565; + *bytesPerPixel = 2; + break; + + default: + assert(0); + return; + } +} + +static inline void CopyTexture(char * dst, const char * src, const unsigned bytesPerPixel, + const unsigned sx, const unsigned sy, const unsigned sw, + const unsigned dx, const unsigned dy, const unsigned dw, + const unsigned w, const unsigned h) +{ + const unsigned bpp = bytesPerPixel; + if (dw == sw && dw == w && sx == 0 && dx == 0) + memcpy(dst + dy * dw * bpp, src + sy * sw * bpp, w * h * bpp); + else + for (unsigned y = 0; y < h; y++) + memcpy(dst + ((dy + y) * dw + dx) * bpp, src + ((sy + y) * sw + sx) * bpp, w * bpp); +} + +void glActiveTexture(GLenum texture) +{ + GLES2_GET_CONST_CONTEXT(ctx); + unsigned index = texture - GL_TEXTURE0; + assert(NELEM(ctx->tex.tmus) > index); +// LOGD("agl2: glActiveTexture %u", index); + ctx->tex.active = index; +} + +void glBindTexture(GLenum target, GLuint texture) +{ + GLES2_GET_CONST_CONTEXT(ctx); +// LOGD("agl2: glBindTexture target=0x%.4X texture=%u active=%u", target, texture, ctx->tex.active); + std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(texture); + GGLTexture * tex = NULL; + if (it != ctx->tex.textures.end()) { + tex = it->second; + if (!tex) { + tex = AllocTexture(); + tex->type = target; + it->second = tex; +// LOGD("agl2: glBindTexture allocTexture"); + } +// else +// LOGD("agl2: glBindTexture bind existing texture"); + assert(target == tex->type); + } else if (0 == texture) { + if (GL_TEXTURE_2D == target) + { + tex = ctx->tex.tex2D; +// LOGD("agl2: glBindTexture bind default tex2D"); + } + else if (GL_TEXTURE_CUBE_MAP == target) + { + tex = ctx->tex.texCube; +// LOGD("agl2: glBindTexture bind default texCube"); + } + else + assert(0); + } else { + if (texture <= ctx->tex.free) + ctx->tex.free = texture + 1; + tex = AllocTexture(); + tex->type = target; + ctx->tex.textures[texture] = tex; +// LOGD("agl2: glBindTexture new texture=%u", texture); + } + ctx->tex.tmus[ctx->tex.active] = tex; +// LOGD("agl2: glBindTexture format=0x%.2X w=%u h=%u levels=%p", tex->format, +// tex->width, tex->height, tex->levels); + ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); +} + +void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) +{ + CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data); +} + +void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) +{ + CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + GLES2_GET_CONST_CONTEXT(ctx); +// LOGD("agl2: glCopyTexImage2D target=0x%.4X internalformat=0x%.4X", target, internalformat); +// LOGD("x=%d y=%d width=%d height=%d border=%d level=%d ", x, y, width, height, border, level); + assert(0 == border); + assert(0 == level); + unsigned bytesPerPixel = 0; + GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN; + GetFormatAndBytesPerPixel(internalformat, &bytesPerPixel, &texFormat); + + assert(texFormat == ctx->rasterizer.frameSurface.format); +// LOGD("texFormat=0x%.2X bytesPerPixel=%d \n", texFormat, bytesPerPixel); + unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size; + + assert(ctx->tex.tmus[ctx->tex.active]); + assert(y + height <= ctx->rasterizer.frameSurface.height); + assert(x + width <= ctx->rasterizer.frameSurface.width); + GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; + tex.width = width; + tex.height = height; + tex.levelCount = 1; + tex.format = texFormat; + switch (target) { + case GL_TEXTURE_2D: + tex.levels = realloc(tex.levels, totalSize); + CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel, + x, y, ctx->rasterizer.frameSurface.width, 0, 0, width, width, height); + break; + default: + assert(0); + return; + } + ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); +} + +void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + // x, y are src offset + // xoffset and yoffset are dst offset + GLES2_GET_CONST_CONTEXT(ctx); +// LOGD("agl2: glCopyTexSubImage2D target=0x%.4X level=%d", target, level); +// LOGD("xoffset=%d yoffset=%d x=%d y=%d width=%d height=%d", xoffset, yoffset, x, y, width, height); + assert(0 == level); + + unsigned bytesPerPixel = 4; + unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size; + + assert(ctx->tex.tmus[ctx->tex.active]); + GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; + + assert(tex.format == ctx->rasterizer.frameSurface.format); + assert(GGL_PIXEL_FORMAT_RGBA_8888 == tex.format); + + const unsigned srcWidth = ctx->rasterizer.frameSurface.width; + const unsigned srcHeight = ctx->rasterizer.frameSurface.height; + + assert(x >= 0 && y >= 0); + assert(xoffset >= 0 && yoffset >= 0); + assert(x + width <= srcWidth); + assert(y + height <= srcHeight); + assert(xoffset + width <= tex.width); + assert(yoffset + height <= tex.height); + + switch (target) { + case GL_TEXTURE_2D: + CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel, + x, y, srcWidth, xoffset, yoffset, tex.width, width, height); + break; + default: + assert(0); + return; + } + ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); +} + +void glDeleteTextures(GLsizei n, const GLuint* textures) +{ + GLES2_GET_CONST_CONTEXT(ctx); + for (unsigned i = 0; i < n; i++) { + std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(textures[i]); + if (it == ctx->tex.textures.end()) + continue; + ctx->tex.free = min(ctx->tex.free, textures[i]); + for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) + if (ctx->tex.tmus[i] == it->second) { + if (GL_TEXTURE_2D == it->second->type) + ctx->tex.tmus[i] = ctx->tex.tex2D; + else if (GL_TEXTURE_CUBE_MAP == it->second->type) + ctx->tex.tmus[i] = ctx->tex.texCube; + else + assert(0); + ctx->tex.UpdateSampler(ctx->iface, i); + } + if (it->second) { + free(it->second->levels); + free(it->second); + } + ctx->tex.textures.erase(it); + } +} + +void glGenTextures(GLsizei n, GLuint* textures) +{ + GLES2_GET_CONST_CONTEXT(ctx); + for (unsigned i = 0; i < n; i++) { + textures[i] = 0; + for (ctx->tex.free; ctx->tex.free < 0xffffffffu; ctx->tex.free++) + if (ctx->tex.textures.find(ctx->tex.free) == ctx->tex.textures.end()) { + ctx->tex.textures[ctx->tex.free] = NULL; + textures[i] = ctx->tex.free; + ctx->tex.free++; + break; + } + assert(textures[i]); + } +} + +void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) +{ + CALL_GL_API(glGetTexParameterfv, target, pname, params); +} +void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) +{ + CALL_GL_API(glGetTexParameteriv, target, pname, params); +} + +GLboolean glIsTexture(GLuint texture) +{ + GLES2_GET_CONST_CONTEXT(ctx); + if (ctx->tex.textures.find(texture) == ctx->tex.textures.end()) + return GL_FALSE; + else + return GL_TRUE; +} + +void glPixelStorei(GLenum pname, GLint param) +{ + GLES2_GET_CONST_CONTEXT(ctx); + assert(GL_UNPACK_ALIGNMENT == pname); + assert(1 == param || 2 == param || 4 == param || 8 == param); +// LOGD("\n*\n* agl2: glPixelStorei not implemented pname=0x%.4X param=%d \n*", pname, param); + ctx->tex.unpack = param; +// CALL_GL_API(glPixelStorei, pname, param); +} +void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, + GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + GLES2_GET_CONST_CONTEXT(ctx); +// LOGD("agl2: glTexImage2D internalformat=0x%.4X format=0x%.4X type=0x%.4X \n", internalformat, format, type); +// LOGD("width=%d height=%d border=%d level=%d pixels=%p \n", width, height, border, level, pixels); + switch (type) { + case GL_UNSIGNED_BYTE: + break; + case GL_UNSIGNED_SHORT_5_6_5: + internalformat = format = GL_UNSIGNED_SHORT_5_6_5; + assert(4 == ctx->tex.unpack); + break; + default: + assert(0); + } + assert(internalformat == format); + assert(0 == border); + if (0 != level) { + LOGD("agl2: glTexImage2D level=%d", level); + return; + } + unsigned bytesPerPixel = 0; + GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN; + GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat); + + assert(texFormat && bytesPerPixel); +// LOGD("texFormat=0x%.2X bytesPerPixel=%d active=%u", texFormat, bytesPerPixel, ctx->tex.active); + unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size; + + assert(ctx->tex.tmus[ctx->tex.active]); + + GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; + tex.width = width; + tex.height = height; + tex.levelCount = 1; + tex.format = texFormat; + + switch (target) { + case GL_TEXTURE_2D: + assert(GL_TEXTURE_2D == ctx->tex.tmus[ctx->tex.active]->type); + offset = 0; + break; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + assert(GL_TEXTURE_CUBE_MAP == ctx->tex.tmus[ctx->tex.active]->type); + assert(width == height); + offset = (target - GL_TEXTURE_CUBE_MAP_POSITIVE_X) * size; + totalSize = 6 * size; + break; + default: + assert(0); + return; + } + + tex.levels = realloc(tex.levels, totalSize); + if (pixels) + CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, 0, 0, width, width, height); + ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); +} + +void glTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ +// LOGD("agl2: glTexParameterf target=0x%.4X pname=0x%.4X param=%f", target, pname, param); + glTexParameteri(target, pname, param); +} +void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) +{ + CALL_GL_API(glTexParameterfv, target, pname, params); +} +void glTexParameteri(GLenum target, GLenum pname, GLint param) +{ + GLES2_GET_CONST_CONTEXT(ctx); +// LOGD("alg2: glTexParameteri target=0x%.0X pname=0x%.4X param=0x%.4X", +// target, pname, param); + assert(ctx->tex.tmus[ctx->tex.active]); + assert(target == ctx->tex.tmus[ctx->tex.active]->type); + GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; + switch (pname) { + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + GGLTexture::GGLTextureWrap wrap; + switch (param) { + case GL_REPEAT: + wrap = GGLTexture::GGL_REPEAT; + break; + case GL_CLAMP_TO_EDGE: + wrap = GGLTexture::GGL_CLAMP_TO_EDGE; + break; + case GL_MIRRORED_REPEAT: + wrap = GGLTexture::GGL_MIRRORED_REPEAT; + break; + default: + assert(0); + return; + } + if (GL_TEXTURE_WRAP_S == pname) + tex.wrapS = wrap; + else + tex.wrapT = wrap; + break; + case GL_TEXTURE_MIN_FILTER: + switch (param) { + case GL_NEAREST: + tex.minFilter = GGLTexture::GGL_NEAREST; + break; + case GL_LINEAR: + tex.minFilter = GGLTexture::GGL_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: +// tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: +// tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_LINEAR; + break; + case GL_LINEAR_MIPMAP_NEAREST: +// tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_NEAREST; + break; + case GL_LINEAR_MIPMAP_LINEAR: +// tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_LINEAR; + break; + default: + assert(0); + return; + } + break; + case GL_TEXTURE_MAG_FILTER: + switch (param) { + case GL_NEAREST: + tex.minFilter = GGLTexture::GGL_NEAREST; + break; + case GL_LINEAR: + tex.minFilter = GGLTexture::GGL_LINEAR; + break; + default: + assert(0); + return; + } + break; + default: + assert(0); + return; + } + // implementation restriction + if (tex.magFilter != tex.minFilter) + tex.magFilter = tex.minFilter = GGLTexture::GGL_LINEAR; + ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); +} +void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) +{ + CALL_GL_API(glTexParameteriv, target, pname, params); +} +void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) +{ + GLES2_GET_CONST_CONTEXT(ctx); +// LOGD("agl2: glTexSubImage2D target=0x%.4X level=%d xoffset=%d yoffset=%d width=%d height=%d format=0x%.4X type=0x%.4X pixels=%p", +// target, level, xoffset, yoffset, width, height, format, type, pixels); + assert(0 == level); + assert(target == ctx->tex.tmus[ctx->tex.active]->type); + switch (type) { + case GL_UNSIGNED_BYTE: + break; + case GL_UNSIGNED_SHORT_5_6_5: + format = GL_UNSIGNED_SHORT_5_6_5; + assert(4 == ctx->tex.unpack); + break; + default: + assert(0); + } + GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; + GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN; + unsigned bytesPerPixel = 0; + GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat); + assert(texFormat == tex.format); + assert(GL_UNSIGNED_BYTE == type); + switch (target) { + case GL_TEXTURE_2D: + CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, xoffset, + yoffset, tex.width, width, height); + break; + default: + assert(0); + } + ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); +} |