diff options
| author | 2010-06-01 19:56:42 -0700 | |
|---|---|---|
| committer | 2010-06-01 19:56:42 -0700 | |
| commit | 847b82d8a6d3cc6969cbeeaf9ca7e879abab482a (patch) | |
| tree | 75dc7b61d605847df777139daceefd72866c46b0 /libs/surfaceflinger/TextureManager.cpp | |
| parent | 8799cdfb012935501e47f15f28d6a8ed90bd464d (diff) | |
| parent | 89bc1395748a0a139db82adbf01166ed6fa79766 (diff) | |
am 89bc1395: Merge "Add more error checking for ndc" into froyo
Merge commit '89bc1395748a0a139db82adbf01166ed6fa79766' into froyo-plus-aosp
* commit '89bc1395748a0a139db82adbf01166ed6fa79766': (392 commits)
Add more error checking for ndc
Add javadoc for camera scene modes.
more clean-up in preparation of bigger changes
Fix a typo in Singleton<>
Avoid copying for input recording frames in CameraSource
Add video frame parameter.
more clean-up of Surfaceflinger's client management
Better sniffing of MPEG4 content by checking for a compatible sub-brand.
Remove the logic in CameraSource using CameraParameters class to find out the buffer size.
Add support for gps altitude EXIF tags.
minor clean-up GLclampx -> GLclampf
clean-up dead-code
Make sure to use filtering while in fixed-size mode
oopsie. forgot to displatch SET_BUFFERS_GEOMETRY
Avoid repeatedly allocating and freeing memory in CameraSource
After failing to create an AudioTrack, only stop the source if we were the ones starting it.
Convert a number of assertions into runtime errors (OggExtractor)
fix [2712278] The preview buffer left some black borders in left and bottom edges
Fix 2667859: change text back to default size
Support for thumbnail extraction in the Matroska extractor.
...
Diffstat (limited to 'libs/surfaceflinger/TextureManager.cpp')
| -rw-r--r-- | libs/surfaceflinger/TextureManager.cpp | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp new file mode 100644 index 000000000000..ee2159b3ffed --- /dev/null +++ b/libs/surfaceflinger/TextureManager.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <ui/GraphicBuffer.h> + +#include <GLES/gl.h> +#include <GLES/glext.h> + +#include <hardware/hardware.h> + +#include "clz.h" +#include "DisplayHardware/DisplayHardware.h" +#include "TextureManager.h" + +namespace android { + +// --------------------------------------------------------------------------- + +TextureManager::TextureManager(uint32_t flags) + : mFlags(flags) +{ +} + +GLuint TextureManager::createTexture() +{ + GLuint textureName = -1; + glGenTextures(1, &textureName); + glBindTexture(GL_TEXTURE_2D, textureName); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + return textureName; +} + +bool TextureManager::isSupportedYuvFormat(int format) +{ + switch (format) { + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_P: + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case HAL_PIXEL_FORMAT_YCbCr_420_I: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return true; + } + return false; +} + +status_t TextureManager::initEglImage(Image* texture, + EGLDisplay dpy, const sp<GraphicBuffer>& buffer) +{ + status_t err = NO_ERROR; + if (!texture->dirty) return err; + + // free the previous image + if (texture->image != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(dpy, texture->image); + texture->image = EGL_NO_IMAGE_KHR; + } + + // construct an EGL_NATIVE_BUFFER_ANDROID + android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); + + // create the new EGLImageKHR + const EGLint attrs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE, EGL_NONE + }; + texture->image = eglCreateImageKHR( + dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + (EGLClientBuffer)clientBuf, attrs); + + if (texture->image != EGL_NO_IMAGE_KHR) { + if (texture->name == -1UL) { + texture->name = createTexture(); + texture->width = 0; + texture->height = 0; + } + glBindTexture(GL_TEXTURE_2D, texture->name); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, + (GLeglImageOES)texture->image); + GLint error = glGetError(); + if (error != GL_NO_ERROR) { + LOGE("glEGLImageTargetTexture2DOES(%p) failed err=0x%04x", + texture->image, error); + err = INVALID_OPERATION; + } else { + // Everything went okay! + texture->dirty = false; + texture->width = clientBuf->width; + texture->height = clientBuf->height; + } + } else { + LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError()); + err = INVALID_OPERATION; + } + return err; +} + +status_t TextureManager::loadTexture(Texture* texture, + const Region& dirty, const GGLSurface& t) +{ + if (texture->name == -1UL) { + texture->name = createTexture(); + texture->width = 0; + texture->height = 0; + } + + glBindTexture(GL_TEXTURE_2D, texture->name); + + /* + * In OpenGL ES we can't specify a stride with glTexImage2D (however, + * GL_UNPACK_ALIGNMENT is a limited form of stride). + * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we + * need to do something reasonable (here creating a bigger texture). + * + * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT); + * + * This situation doesn't happen often, but some h/w have a limitation + * for their framebuffer (eg: must be multiple of 8 pixels), and + * we need to take that into account when using these buffers as + * textures. + * + * This should never be a problem with POT textures + */ + + int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format)); + unpack = 1 << ((unpack > 3) ? 3 : unpack); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); + + /* + * round to POT if needed + */ + if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { + texture->NPOTAdjust = true; + } + + if (texture->NPOTAdjust) { + // find the smallest power-of-two that will accommodate our surface + texture->potWidth = 1 << (31 - clz(t.width)); + texture->potHeight = 1 << (31 - clz(t.height)); + if (texture->potWidth < t.width) texture->potWidth <<= 1; + if (texture->potHeight < t.height) texture->potHeight <<= 1; + texture->wScale = float(t.width) / texture->potWidth; + texture->hScale = float(t.height) / texture->potHeight; + } else { + texture->potWidth = t.width; + texture->potHeight = t.height; + } + + Rect bounds(dirty.bounds()); + GLvoid* data = 0; + if (texture->width != t.width || texture->height != t.height) { + texture->width = t.width; + texture->height = t.height; + + // texture size changed, we need to create a new one + bounds.set(Rect(t.width, t.height)); + if (t.width == texture->potWidth && + t.height == texture->potHeight) { + // we can do it one pass + data = t.data; + } + + if (t.format == HAL_PIXEL_FORMAT_RGB_565) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGB, texture->potWidth, texture->potHeight, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture->potWidth, texture->potHeight, 0, + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); + } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || + t.format == HAL_PIXEL_FORMAT_RGBX_8888) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture->potWidth, texture->potHeight, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + } else if (isSupportedYuvFormat(t.format)) { + // just show the Y plane of YUV buffers + glTexImage2D(GL_TEXTURE_2D, 0, + GL_LUMINANCE, texture->potWidth, texture->potHeight, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } else { + // oops, we don't handle this format! + LOGE("texture=%d, using format %d, which is not " + "supported by the GL", texture->name, t.format); + } + } + if (!data) { + if (t.format == HAL_PIXEL_FORMAT_RGB_565) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + t.data + bounds.top*t.stride*2); + } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, + t.data + bounds.top*t.stride*2); + } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || + t.format == HAL_PIXEL_FORMAT_RGBX_8888) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride*4); + } else if (isSupportedYuvFormat(t.format)) { + // just show the Y plane of YUV buffers + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_LUMINANCE, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride); + } + } + return NO_ERROR; +} + +// --------------------------------------------------------------------------- + +}; // namespace android |