Merge change 24509 into eclair
* changes:
Addressed reviewer comments.
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index e66b00f..3c2dc2b 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -552,17 +552,6 @@
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
- const char *format = params.getPreviewFormat();
- int fmt;
- if (!strcmp(format, "yuv422i-yuyv"))
- fmt = OVERLAY_FORMAT_YCbYCr_422_I;
- else if (!strcmp(format, "rgb565"))
- fmt = OVERLAY_FORMAT_RGB_565;
- else {
- LOGE("Invalid preview format for overlays");
- return -EINVAL;
- }
-
if ( w != mOverlayW || h != mOverlayH )
{
// Force the destruction of any previous overlay
@@ -574,7 +563,7 @@
status_t ret = NO_ERROR;
if (mSurface != 0) {
if (mOverlayRef.get() == NULL) {
- mOverlayRef = mSurface->createOverlay(w, h, fmt);
+ mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT);
if ( mOverlayRef.get() == NULL )
{
LOGE("Overlay Creation Failed!");
diff --git a/include/private/ui/SharedBufferStack.h b/include/private/ui/SharedBufferStack.h
index 2bd5344..6181f55 100644
--- a/include/private/ui/SharedBufferStack.h
+++ b/include/private/ui/SharedBufferStack.h
@@ -85,6 +85,7 @@
public:
SharedBufferStack();
+ void init(int32_t identity);
status_t setDirtyRegion(int buffer, const Region& reg);
Region getDirtyRegion(int buffer) const;
@@ -93,12 +94,12 @@
volatile int32_t available; // number of dequeue-able buffers
volatile int32_t queued; // number of buffers waiting for post
volatile int32_t inUse; // buffer currently in use by SF
+ volatile status_t status; // surface's status code
// not part of the conditions
volatile int32_t reallocMask;
int32_t identity; // surface's identity (const)
- status_t status; // surface's status code
int32_t reserved32[13];
FlatRegion dirtyRegion[NUM_BUFFER_MAX]; // 12*4=48 bytes
};
@@ -114,7 +115,6 @@
status_t validate(size_t token) const;
uint32_t getIdentity(size_t token) const;
- status_t setIdentity(size_t token, uint32_t identity);
private:
friend class SharedBufferBase;
@@ -168,10 +168,11 @@
template <typename T>
status_t SharedBufferBase::waitForCondition(T condition)
{
+ const SharedBufferStack& stack( *mSharedStack );
SharedClient& client( *mSharedClient );
const nsecs_t TIMEOUT = s2ns(1);
Mutex::Autolock _l(client.lock);
- while (!condition()) {
+ while ((condition()==false) && (stack.status == NO_ERROR)) {
status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
// handle errors and timeouts
@@ -195,7 +196,7 @@
}
}
}
- return NO_ERROR;
+ return stack.status;
}
@@ -261,13 +262,15 @@
class SharedBufferServer : public SharedBufferBase
{
public:
- SharedBufferServer(SharedClient* sharedClient, int surface, int num);
+ SharedBufferServer(SharedClient* sharedClient, int surface, int num,
+ int32_t identity);
ssize_t retireAndLock();
status_t unlock(int buffer);
+ void setStatus(status_t status);
status_t reallocate();
status_t assertReallocate(int buffer);
-
+
Region getDirtyRegion(int buffer) const;
private:
@@ -283,6 +286,12 @@
inline ssize_t operator()();
};
+ struct StatusUpdate : public UpdateBase {
+ const status_t status;
+ inline StatusUpdate(SharedBufferBase* sbb, status_t status);
+ inline ssize_t operator()();
+ };
+
struct ReallocateCondition : public ConditionBase {
int buf;
inline ReallocateCondition(SharedBufferBase* sbb, int buf);
diff --git a/include/utils/threads.h b/include/utils/threads.h
index 0fc533f..f5304f7 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -90,6 +90,11 @@
ANDROID_TGROUP_MAX = ANDROID_TGROUP_FG_BOOST,
};
+typedef enum {
+ SP_BACKGROUND = 0,
+ SP_FOREGROUND = 1,
+} SchedPolicy;
+
// Create and run a new thread.
extern int androidCreateThread(android_thread_func_t, void *);
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 651e7cf..d893f0a 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -103,10 +103,22 @@
}
// initialize EGL
- const EGLint attribs[] = {
+ EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE, 0,
EGL_NONE
};
+
+ // debug: disable h/w rendering
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("debug.sf.hw", property, NULL) > 0) {
+ if (atoi(property) == 0) {
+ LOGW("H/W composition disabled");
+ attribs[2] = EGL_CONFIG_CAVEAT;
+ attribs[3] = EGL_SLOW_CONFIG;
+ }
+ }
+
EGLint w, h, dummy;
EGLint numConfigs=0;
EGLSurface surface;
@@ -193,7 +205,6 @@
mDpiY = mNativeWindow->ydpi;
mRefreshRate = fbDev->fps;
- char property[PROPERTY_VALUE_MAX];
/* Read density from build-specific ro.sf.lcd_density property
* except if it is overridden by qemu.sf.lcd_density.
*/
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index ecb6b32..6275910 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -49,13 +49,12 @@
Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& c, int32_t i)
- : LayerBaseClient(flinger, display, c, i), lcblk(NULL),
+ : LayerBaseClient(flinger, display, c, i),
mSecure(false),
mNeedsBlending(true)
{
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
- lcblk = new SharedBufferServer(c->ctrlblk, i, NUM_BUFFERS);
mFrontBufferIndex = lcblk->getFrontBuffer();
}
@@ -63,8 +62,14 @@
{
destroy();
// the actual buffers will be destroyed here
- delete lcblk;
+}
+// called with SurfaceFlinger::mStateLock as soon as the layer is entered
+// in the purgatory list
+void Layer::onRemoved()
+{
+ // wake up the condition
+ lcblk->setStatus(NO_INIT);
}
void Layer::destroy()
@@ -79,7 +84,9 @@
eglDestroyImageKHR(dpy, mTextures[i].image);
mTextures[i].image = EGL_NO_IMAGE_KHR;
}
+ Mutex::Autolock _l(mLock);
mBuffers[i].clear();
+ mWidth = mHeight = 0;
}
mSurface.clear();
}
@@ -213,6 +220,16 @@
sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage)
{
+ sp<Buffer> buffer;
+
+ // this ensures our client doesn't go away while we're accessing
+ // the shared area.
+ sp<Client> ourClient(client.promote());
+ if (ourClient == 0) {
+ // oops, the client is already gone
+ return buffer;
+ }
+
/*
* This is called from the client's Surface::dequeue(). This can happen
* at any time, especially while we're in the middle of using the
@@ -225,12 +242,21 @@
*/
status_t err = lcblk->assertReallocate(index);
LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
+ if (err != NO_ERROR) {
+ // the surface may have died
+ return buffer;
+ }
- Mutex::Autolock _l(mLock);
- uint32_t w = mWidth;
- uint32_t h = mHeight;
-
- sp<Buffer>& buffer(mBuffers[index]);
+ uint32_t w, h;
+ { // scope for the lock
+ Mutex::Autolock _l(mLock);
+ w = mWidth;
+ h = mHeight;
+ buffer = mBuffers[index];
+ mBuffers[index].clear();
+ }
+
+
if (buffer->getStrongCount() == 1) {
err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags);
} else {
@@ -253,8 +279,16 @@
}
if (err == NO_ERROR && buffer->handle != 0) {
- // texture is now dirty...
- mTextures[index].dirty = true;
+ Mutex::Autolock _l(mLock);
+ if (mWidth && mHeight) {
+ // and we have new buffer
+ mBuffers[index] = buffer;
+ // texture is now dirty...
+ mTextures[index].dirty = true;
+ } else {
+ // oops we got killed while we were allocating the buffer
+ buffer.clear();
+ }
}
return buffer;
}
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 3b4489e..2e8173d 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -51,10 +51,6 @@
static const char* const typeID;
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
-
-
- SharedBufferServer* lcblk;
-
Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
@@ -88,6 +84,8 @@
return mBuffers[mFrontBufferIndex];
}
+ virtual void onRemoved();
+
void reloadTexture(const Region& dirty);
sp<SurfaceBuffer> requestBuffer(int index, int usage);
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 62e41b0..1f22488 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -642,9 +642,12 @@
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
- : LayerBase(flinger, display), client(client),
+ : LayerBase(flinger, display), lcblk(NULL), client(client),
mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
+ lcblk = new SharedBufferServer(
+ client->ctrlblk, i, NUM_BUFFERS,
+ mIdentity);
}
void LayerBaseClient::onFirstRef()
@@ -652,8 +655,6 @@
sp<Client> client(this->client.promote());
if (client != 0) {
client->bindLayer(this, mIndex);
- // Initialize this layer's identity
- client->ctrlblk->setIdentity(mIndex, mIdentity);
}
}
@@ -663,6 +664,7 @@
if (client != 0) {
client->free(mIndex);
}
+ delete lcblk;
}
int32_t LayerBaseClient::serverIndex() const
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 78bb4bf..3a52240 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -292,13 +292,16 @@
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
+ // lcblk is (almost) only accessed from the main SF thread, in the places
+ // where it's not, a reference to Client must be held
+ SharedBufferServer* lcblk;
+
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~LayerBaseClient();
virtual void onFirstRef();
- wp<Client> client;
-// SharedBufferServer* lcblk;
+ const wp<Client> client;
inline uint32_t getIdentity() const { return mIdentity; }
inline int32_t clientIndex() const { return mIndex; }
@@ -308,6 +311,7 @@
sp<Surface> getSurface();
virtual sp<Surface> createSurface() const;
+ virtual void onRemoved() { }
class Surface : public BnSurface
{
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 00abd5a..e14f35b 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -24,6 +24,7 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+#include "clz.h"
#include "BlurFilter.h"
#include "LayerBlur.h"
#include "SurfaceFlinger.h"
@@ -40,7 +41,8 @@
LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
: LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
- mRefreshCache(true), mCacheAge(0), mTextureName(-1U)
+ mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
+ mWidthScale(1.0f), mHeightScale(1.0f)
{
}
@@ -164,11 +166,26 @@
bl.format = GGL_PIXEL_FORMAT_RGB_565;
bl.data = (GGLubyte*)pixels;
blurFilter(&bl, 8, 2);
-
- // NOTE: this works only because we have POT. we'd have to round the
- // texture size up, otherwise.
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+
+ if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+ mWidthScale = 1.0f / w;
+ mHeightScale =-1.0f / h;
+ mYOffset = 0;
+ } else {
+ GLuint tw = 1 << (31 - clz(w));
+ GLuint th = 1 << (31 - clz(h));
+ if (tw < w) tw <<= 1;
+ if (th < h) th <<= 1;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+ mWidthScale = 1.0f / tw;
+ mHeightScale =-1.0f / th;
+ mYOffset = th-h;
+ }
free((void*)pixels);
}
@@ -184,7 +201,12 @@
glDisable(GL_BLEND);
}
- glDisable(GL_DITHER);
+ if (mFlags & DisplayHardware::SLOW_CONFIG) {
+ glDisable(GL_DITHER);
+ } else {
+ glEnable(GL_DITHER);
+ }
+
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -194,8 +216,8 @@
// This is a very rare scenario.
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
- glScalef(1.0f/w, -1.0f/h, 1);
- glTranslatef(-x, -y, 0);
+ glScalef(mWidthScale, mHeightScale, 1);
+ glTranslatef(-x, mYOffset - y, 0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FIXED, 0, mVertices);
glTexCoordPointer(2, GL_FIXED, 0, mVertices);
@@ -205,6 +227,7 @@
glScissor(r.left, sy, r.width(), r.height());
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} else {
// NOTE: this is marginally faster with the software gl, because
// glReadPixels() reads the fb bottom-to-top, however we'll
@@ -221,8 +244,6 @@
}
}
}
-
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index 0c3e6eb..bf36ae4 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -56,6 +56,9 @@
mutable bool mAutoRefreshPending;
nsecs_t mCacheAge;
mutable GLuint mTextureName;
+ mutable GLfloat mWidthScale;
+ mutable GLfloat mHeightScale;
+ mutable GLfloat mYOffset;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index b368db6..8685f99 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -654,6 +654,7 @@
// some layers might have been removed, so
// we need to update the regions they're exposing.
if (mLayersRemoved) {
+ mLayersRemoved = false;
mVisibleRegionsDirty = true;
const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
const size_t count = previousLayers.size();
@@ -1093,9 +1094,6 @@
void SurfaceFlinger::free_resources_l()
{
- // Destroy layers that were removed
- mLayersRemoved = false;
-
// free resources associated with disconnected clients
Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
const size_t count = disconnectedClients.size();
@@ -1321,11 +1319,15 @@
* to wait for all client's references to go away first).
*/
+ status_t err = NAME_NOT_FOUND;
Mutex::Autolock _l(mStateLock);
sp<LayerBaseClient> layer = getLayerUser_l(index);
- status_t err = purgatorizeLayer_l(layer);
- if (err == NO_ERROR) {
- setTransactionFlags(eTransactionNeeded);
+ if (layer != 0) {
+ err = purgatorizeLayer_l(layer);
+ if (err == NO_ERROR) {
+ layer->onRemoved();
+ setTransactionFlags(eTransactionNeeded);
+ }
}
return err;
}
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
index 5995af5..436d793 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/ui/SharedBufferStack.cpp
@@ -53,21 +53,20 @@
return uint32_t(surfaces[token].identity);
}
-status_t SharedClient::setIdentity(size_t token, uint32_t identity) {
- if (token >= NUM_LAYERS_MAX)
- return BAD_INDEX;
- surfaces[token].identity = identity;
- return NO_ERROR;
-}
-
// ----------------------------------------------------------------------------
SharedBufferStack::SharedBufferStack()
- : inUse(-1), identity(-1), status(NO_ERROR)
{
}
+void SharedBufferStack::init(int32_t i)
+{
+ inUse = -1;
+ status = NO_ERROR;
+ identity = i;
+}
+
status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
{
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
@@ -231,16 +230,46 @@
return head;
}
+SharedBufferServer::StatusUpdate::StatusUpdate(
+ SharedBufferBase* sbb, status_t status)
+ : UpdateBase(sbb), status(status) {
+}
+
+ssize_t SharedBufferServer::StatusUpdate::operator()() {
+ android_atomic_write(status, &stack.status);
+ return NO_ERROR;
+}
+
// ============================================================================
SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
int surface, int num)
: SharedBufferBase(sharedClient, surface, num), tail(0)
{
+ SharedBufferStack& stack( *mSharedStack );
+ int32_t avail;
+ int32_t head;
+ // we need to make sure we read available and head coherently,
+ // w.r.t RetireUpdate.
+ do {
+ avail = stack.available;
+ head = stack.head;
+ } while (stack.available != avail);
+ tail = head - avail + 1;
+ if (tail < 0) {
+ tail += num;
+ }
}
ssize_t SharedBufferClient::dequeue()
{
+ SharedBufferStack& stack( *mSharedStack );
+
+ if (stack.head == tail && stack.available == 2) {
+ LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
+ tail, stack.head, stack.available, stack.queued);
+ }
+
//LOGD("[%d] about to dequeue a buffer",
// mSharedStack->identity);
DequeueCondition condition(this);
@@ -248,8 +277,6 @@
if (err != NO_ERROR)
return ssize_t(err);
-
- SharedBufferStack& stack( *mSharedStack );
// NOTE: 'stack.available' is part of the conditions, however
// decrementing it, never changes any conditions, so we don't need
// to do this as part of an update.
@@ -261,6 +288,7 @@
tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s",
dequeued, tail, dump("").string());
+
return dequeued;
}
@@ -302,9 +330,10 @@
// ----------------------------------------------------------------------------
SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
- int surface, int num)
+ int surface, int num, int32_t identity)
: SharedBufferBase(sharedClient, surface, num)
{
+ mSharedStack->init(identity);
mSharedStack->head = num-1;
mSharedStack->available = num;
mSharedStack->queued = 0;
@@ -316,7 +345,7 @@
{
RetireUpdate update(this, mNumBuffers);
ssize_t buf = updateCondition( update );
- LOGD_IF(DEBUG_ATOMICS, "retire=%d, %s", int(buf), dump("").string());
+ LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", int(buf), dump("").string());
return buf;
}
@@ -327,6 +356,12 @@
return err;
}
+void SharedBufferServer::setStatus(status_t status)
+{
+ StatusUpdate update(this, status);
+ updateCondition( update );
+}
+
status_t SharedBufferServer::reallocate()
{
SharedBufferStack& stack( *mSharedStack );
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 4d3c2f4..90e6d29 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -118,10 +118,10 @@
/*
* If the active textures are EGLImage, they need to be locked before
- * they can be used.
- *
+ * they can be used.
+ *
* FIXME: code below is far from being optimal
- *
+ *
*/
void ogles_lock_textures(ogles_context_t* c)
@@ -409,6 +409,49 @@
return 0;
}
+static size_t 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)
@@ -443,6 +486,7 @@
}
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;
@@ -652,7 +696,7 @@
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;
@@ -799,7 +843,7 @@
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;
@@ -1091,6 +1135,12 @@
GGLSurface* surface;
// 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;