summaryrefslogtreecommitdiffstats
path: root/opengl/libagl
diff options
context:
space:
mode:
Diffstat (limited to 'opengl/libagl')
-rw-r--r--opengl/libagl/Android.mk17
-rw-r--r--opengl/libagl/TextureObjectManager.cpp47
-rw-r--r--opengl/libagl/TextureObjectManager.h69
-rw-r--r--opengl/libagl/array.cpp126
-rw-r--r--opengl/libagl/copybit.cpp370
-rw-r--r--opengl/libagl/copybit.h75
-rw-r--r--opengl/libagl/egl.cpp629
-rw-r--r--opengl/libagl/state.cpp82
-rw-r--r--opengl/libagl/texture.cpp262
-rw-r--r--opengl/libagl/texture.h10
10 files changed, 1374 insertions, 313 deletions
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 3ce0414..060f3c6 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -6,6 +6,9 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+# Set to 1 to use gralloc and copybits
+LIBAGL_USE_GRALLOC_COPYBITS := 1
+
LOCAL_SRC_FILES:= \
egl.cpp \
state.cpp \
@@ -32,10 +35,20 @@ ifneq ($(TARGET_SIMULATOR),true)
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
endif
-LOCAL_SHARED_LIBRARIES := libcutils libutils libpixelflinger
+ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1)
+ LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS -I$(LOCAL_PATH)/../../../../hardware/libhardware/modules/gralloc
+ LOCAL_SRC_FILES += copybit.cpp
+endif
+
+LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_LDLIBS := -lpthread -ldl
-LOCAL_MODULE:= libagl
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
+LOCAL_MODULE:= libGLES_android
include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp
index ce31854..9deb2cf 100644
--- a/opengl/libagl/TextureObjectManager.cpp
+++ b/opengl/libagl/TextureObjectManager.cpp
@@ -1,16 +1,16 @@
/*
** 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
+ ** 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
+ ** 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
+ ** 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.
*/
@@ -19,11 +19,13 @@
#include "context.h"
#include "TextureObjectManager.h"
+#include <private/ui/android_natives_priv.h>
+
namespace android {
// ----------------------------------------------------------------------------
EGLTextureObject::EGLTextureObject()
- : mCount(0), mSize(0)
+ : mSize(0)
{
init();
}
@@ -53,6 +55,10 @@ void EGLTextureObject::init()
memset(crop_rect, 0, sizeof(crop_rect));
generate_mipmap = GL_FALSE;
direct = GL_FALSE;
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ copybits_fd = -1;
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+ buffer = 0;
}
void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old)
@@ -123,6 +129,7 @@ status_t EGLTextureObject::setSurface(GGLSurface const* s)
}
surface = *s;
internalformat = 0;
+ buffer = 0;
// we should keep the crop_rect, but it's delicate because
// the new size of the surface could make it invalid.
@@ -141,12 +148,26 @@ status_t EGLTextureObject::setSurface(GGLSurface const* s)
return NO_ERROR;
}
+status_t EGLTextureObject::setImage(android_native_buffer_t* native_buffer)
+{
+ GGLSurface sur;
+ sur.version = sizeof(GGLSurface);
+ sur.width = native_buffer->width;
+ sur.height= native_buffer->height;
+ sur.stride= native_buffer->stride;
+ sur.format= native_buffer->format;
+ sur.data = 0;
+ setSurface(&sur);
+ buffer = native_buffer;
+ return NO_ERROR;
+}
+
status_t EGLTextureObject::reallocate(
GLint level, int w, int h, int s,
int format, int compressedFormat, int bpr)
{
const size_t size = h * bpr;
- if (level == 0)
+ if (level == 0)
{
if (size!=mSize || !surface.data) {
if (mSize && surface.data) {
@@ -177,9 +198,9 @@ status_t EGLTextureObject::reallocate(
return NO_MEMORY;
}
- LOGW_IF(level-1 >= mNumExtraLod,
+ LOGW_IF(level-1 >= mNumExtraLod,
"specifying mipmap level %d, but # of level is %d",
- level, mNumExtraLod+1);
+ level, mNumExtraLod+1);
GGLSurface& mipmap = editMip(level);
if (mipmap.data)
@@ -224,7 +245,7 @@ status_t EGLTextureObject::reallocate(
// ----------------------------------------------------------------------------
EGLSurfaceManager::EGLSurfaceManager()
- : TokenManager(), mCount(0)
+ : TokenManager()
{
}
diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h
index 74ed1a4..e0eadf1 100644
--- a/opengl/libagl/TextureObjectManager.h
+++ b/opengl/libagl/TextureObjectManager.h
@@ -1,16 +1,16 @@
/*
** 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
+** 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
+** 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
+** 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.
*/
@@ -30,6 +30,7 @@
#include <private/pixelflinger/ggl_context.h>
#include <GLES/gl.h>
+#include <EGL/egl.h>
#include "Tokenizer.h"
#include "TokenManager.h"
@@ -39,22 +40,20 @@ namespace android {
// ----------------------------------------------------------------------------
-class EGLTextureObject
+class EGLTextureObject : public LightRefBase<EGLTextureObject>
{
public:
EGLTextureObject();
~EGLTextureObject();
- // protocol for sp<>
- inline void incStrong(const void* id) const;
- inline void decStrong(const void* id) const;
- inline uint32_t getStrongCount() const;
+ status_t setSurface(GGLSurface const* s);
+ status_t setImage(android_native_buffer_t* buffer);
+ void setImageBits(void* vaddr) { surface.data = (GGLubyte*)vaddr; }
- status_t setSurface(GGLSurface const* s);
status_t reallocate(GLint level,
int w, int h, int s,
int format, int compressedFormat, int bpr);
- inline size_t size() const;
+ inline size_t size() const { return mSize; }
const GGLSurface& mip(int lod) const;
GGLSurface& editMip(int lod);
bool hasMipmaps() const { return mMipmaps!=0; }
@@ -65,7 +64,6 @@ private:
status_t allocateMipmaps();
void freeMipmaps();
void init();
- mutable int32_t mCount;
size_t mSize;
GGLSurface *mMipmaps;
int mNumExtraLod;
@@ -81,36 +79,22 @@ public:
GLint crop_rect[4];
GLint generate_mipmap;
GLint direct;
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ int copybits_fd;
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+ android_native_buffer_t* buffer;
};
-void EGLTextureObject::incStrong(const void* id) const {
- android_atomic_inc(&mCount);
-}
-void EGLTextureObject::decStrong(const void* id) const {
- if (android_atomic_dec(&mCount) == 1) {
- delete this;
- }
-}
-uint32_t EGLTextureObject::getStrongCount() const {
- return mCount;
-}
-size_t EGLTextureObject::size() const {
- return mSize;
-}
-
// ----------------------------------------------------------------------------
-class EGLSurfaceManager : public TokenManager
+class EGLSurfaceManager :
+ public LightRefBase<EGLSurfaceManager>,
+ public TokenManager
{
public:
EGLSurfaceManager();
~EGLSurfaceManager();
- // protocol for sp<>
- inline void incStrong(const void* id) const;
- inline void decStrong(const void* id) const;
- typedef void weakref_type;
-
sp<EGLTextureObject> createTexture(GLuint name);
sp<EGLTextureObject> removeTexture(GLuint name);
sp<EGLTextureObject> replaceTexture(GLuint name);
@@ -118,21 +102,10 @@ public:
sp<EGLTextureObject> texture(GLuint name);
private:
- mutable int32_t mCount;
mutable Mutex mLock;
KeyedVector< GLuint, sp<EGLTextureObject> > mTextures;
};
-void EGLSurfaceManager::incStrong(const void* id) const {
- android_atomic_inc(&mCount);
-}
-void EGLSurfaceManager::decStrong(const void* id) const {
- if (android_atomic_dec(&mCount) == 1) {
- delete this;
- }
-}
-
-
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp
index 8fa7566..6d2cc91 100644
--- a/opengl/libagl/array.cpp
+++ b/opengl/libagl/array.cpp
@@ -1,16 +1,16 @@
-/*
+/*
** 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
+** 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
+** 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
+** 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.
*/
@@ -26,6 +26,9 @@
#include "primitives.h"
#include "texture.h"
#include "BufferObjectManager.h"
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include "copybit.h"
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
// ----------------------------------------------------------------------------
@@ -250,7 +253,7 @@ static void fetchExpand3s(ogles_context_t*, GLfixed* v, const GLshort* p) {
v[2] = GGL_S_TO_X(p[2]);
}
-typedef array_t::fetcher_t fn_t;
+typedef array_t::fetcher_t fn_t;
static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x}
{ 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0,
@@ -334,7 +337,7 @@ void array_t::init(
this->bounds = count;
}
-inline void array_t::resolve()
+inline void array_t::resolve()
{
physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer;
}
@@ -465,7 +468,7 @@ vertex_t* cache_vertex(ogles_context_t* c, vertex_t* v, uint32_t index)
// We compute directly the index of a "free" entry from the locked
// state of v[2] and v[3].
v = c->vc.vBuffer + 2;
- v += v[0].locked | (v[1].locked<<1);
+ v += v[0].locked | (v[1].locked<<1);
}
// note: compileElement clears v->flags
c->arrays.compileElement(c, v, index);
@@ -480,7 +483,7 @@ vertex_t* fetch_vertex(ogles_context_t* c, size_t index)
#if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED
- vertex_t* const v = c->vc.vCache +
+ vertex_t* const v = c->vc.vCache +
(index & (vertex_cache_t::VERTEX_CACHE_SIZE-1));
if (ggl_likely(v->index == index)) {
@@ -491,7 +494,7 @@ vertex_t* fetch_vertex(ogles_context_t* c, size_t index)
#elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU
- vertex_t* v = c->vc.vCache +
+ vertex_t* v = c->vc.vCache +
(index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2;
// always record LRU in v[0]
@@ -532,12 +535,12 @@ void drawPrimitivesPoints(ogles_context_t* c, GLint first, GLsizei count)
return;
// vertex cache size must be multiple of 1
- const GLsizei vcs =
+ const GLsizei vcs =
(vertex_cache_t::VERTEX_BUFFER_SIZE +
vertex_cache_t::VERTEX_CACHE_SIZE);
do {
vertex_t* v = c->vc.vBuffer;
- GLsizei num = count > vcs ? vcs : count;
+ GLsizei num = count > vcs ? vcs : count;
c->arrays.cull = vertex_t::CLIP_ALL;
c->arrays.compileElements(c, v, first, num);
first += num;
@@ -569,13 +572,13 @@ void drawPrimitivesLineStrip(ogles_context_t* c, GLint first, GLsizei count)
count -= 1;
// vertex cache size must be multiple of 1
- const GLsizei vcs =
+ const GLsizei vcs =
(vertex_cache_t::VERTEX_BUFFER_SIZE +
vertex_cache_t::VERTEX_CACHE_SIZE - 1);
do {
- v0 = c->vc.vBuffer + 0;
+ v0 = c->vc.vBuffer + 0;
v = c->vc.vBuffer + 1;
- GLsizei num = count > vcs ? vcs : count;
+ GLsizei num = count > vcs ? vcs : count;
c->arrays.compileElements(c, v, first, num);
first += num;
count -= num;
@@ -602,7 +605,7 @@ void drawPrimitivesLineLoop(ogles_context_t* c, GLint first, GLsizei count)
return;
drawPrimitivesLineStrip(c, first, count);
if (ggl_likely(count >= 3)) {
- vertex_t* v0 = c->vc.vBuffer;
+ vertex_t* v0 = c->vc.vBuffer;
vertex_t* v1 = c->vc.vBuffer + 1;
c->arrays.compileElement(c, v1, first);
const uint32_t cc = v0->flags & v1->flags;
@@ -617,12 +620,12 @@ void drawPrimitivesLines(ogles_context_t* c, GLint first, GLsizei count)
return;
// vertex cache size must be multiple of 2
- const GLsizei vcs =
+ const GLsizei vcs =
((vertex_cache_t::VERTEX_BUFFER_SIZE +
vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2;
do {
vertex_t* v = c->vc.vBuffer;
- GLsizei num = count > vcs ? vcs : count;
+ GLsizei num = count > vcs ? vcs : count;
c->arrays.cull = vertex_t::CLIP_ALL;
c->arrays.compileElements(c, v, first, num);
first += num;
@@ -662,14 +665,14 @@ static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c,
// because it allows us to preserve the same winding when the whole
// batch is culled. We also need 2 extra vertices in the array, because
// we always keep the two first ones.
- const GLsizei vcs =
+ const GLsizei vcs =
((vertex_cache_t::VERTEX_BUFFER_SIZE +
vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2;
do {
- v0 = c->vc.vBuffer + 0;
- v1 = c->vc.vBuffer + 1;
+ v0 = c->vc.vBuffer + 0;
+ v1 = c->vc.vBuffer + 1;
v = c->vc.vBuffer + 2;
- GLsizei num = count > vcs ? vcs : count;
+ GLsizei num = count > vcs ? vcs : count;
c->arrays.compileElements(c, v, first, num);
first += num;
count -= num;
@@ -697,13 +700,19 @@ static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c,
} while (count > 0);
}
-void drawPrimitivesTriangleStrip(ogles_context_t* c,
+void drawPrimitivesTriangleStrip(ogles_context_t* c,
GLint first, GLsizei count) {
drawPrimitivesTriangleFanOrStrip(c, first, count, 1);
}
void drawPrimitivesTriangleFan(ogles_context_t* c,
GLint first, GLsizei count) {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ if (drawTrangleFanWithCopybit(c, first, count)) {
+ return;
+ }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
drawPrimitivesTriangleFanOrStrip(c, first, count, 2);
}
@@ -713,12 +722,12 @@ void drawPrimitivesTriangles(ogles_context_t* c, GLint first, GLsizei count)
return;
// vertex cache size must be multiple of 3
- const GLsizei vcs =
+ const GLsizei vcs =
((vertex_cache_t::VERTEX_BUFFER_SIZE +
vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3;
do {
vertex_t* v = c->vc.vBuffer;
- GLsizei num = count > vcs ? vcs : count;
+ GLsizei num = count > vcs ? vcs : count;
c->arrays.cull = vertex_t::CLIP_ALL;
c->arrays.compileElements(c, v, first, num);
first += num;
@@ -779,11 +788,11 @@ void drawIndexedPrimitivesLineStrip(ogles_context_t* c,
{
if (ggl_unlikely(count < 2))
return;
-
+
vertex_t * const v = c->vc.vBuffer;
vertex_t* v0 = v;
vertex_t* v1;
-
+
const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
c->arrays.compileElement(c, v0, read_index(type, indices));
count -= 1;
@@ -806,11 +815,11 @@ void drawIndexedPrimitivesLineLoop(ogles_context_t* c,
drawIndexedPrimitivesLines(c, count, indices);
return;
}
-
+
vertex_t * const v = c->vc.vBuffer;
vertex_t* v0 = v;
vertex_t* v1;
-
+
const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
c->arrays.compileElement(c, v0, read_index(type, indices));
count -= 1;
@@ -825,7 +834,7 @@ void drawIndexedPrimitivesLineLoop(ogles_context_t* c,
} while (count);
v1->locked = 0;
- v1 = c->vc.vBuffer;
+ v1 = c->vc.vBuffer;
const uint32_t cc = v0->flags & v1->flags;
if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
c->prims.renderLine(c, v0, v1);
@@ -861,7 +870,7 @@ static void drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t* c,
if (ggl_unlikely(count < 3))
return;
-
+
vertex_t * const v = c->vc.vBuffer;
vertex_t* v0 = v;
vertex_t* v1 = v+1;
@@ -981,17 +990,17 @@ void compileElements__3x_full(ogles_context_t* c,
const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first);
const size_t stride = c->arrays.vertex.stride / 4;
// const GLfixed* const& m = c->transforms.mvp.matrix.m;
-
+
GLfixed m[16];
memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m));
-
+
do {
const GLfixed rx = vp[0];
const GLfixed ry = vp[1];
const GLfixed rz = vp[2];
vp += stride;
v->index = first++;
- v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]);
+ v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]);
v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]);
@@ -1019,7 +1028,7 @@ void compileElements__3x_full(ogles_context_t* c,
#pragma mark clippers
#endif
-static void clipVec4(vec4_t& nv,
+static void clipVec4(vec4_t& nv,
GLfixed t, const vec4_t& s, const vec4_t& p)
{
for (int i=0; i<4 ; i++)
@@ -1082,10 +1091,10 @@ void validate_arrays(ogles_context_t* c, GLenum mode)
// automatically turn it off (in fact we could when the 4th coordinate
// is not spcified in the vertex array).
// W interpolation is never needed for points.
- GLboolean perspective =
+ GLboolean perspective =
c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS);
c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective);
-
+
// set anti-aliasing
GLboolean smooth = GL_FALSE;
switch (mode) {
@@ -1116,7 +1125,7 @@ void validate_arrays(ogles_context_t* c, GLenum mode)
if (enables & GGL_ENABLE_TMUS) { // needs texture transforms
want |= transform_state_t::TEXTURE;
}
- if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) {
+ if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) {
want |= transform_state_t::MODELVIEW; // needs eye coords
}
ogles_validate_transform(c, want);
@@ -1135,18 +1144,18 @@ void validate_arrays(ogles_context_t* c, GLenum mode)
c->arrays.mv_transform =
c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2];
-
+
/*
* ***********************************************************************
* pick fetchers
* ***********************************************************************
*/
-
+
array_machine_t& am = c->arrays;
am.vertex.fetch = fetchNop;
am.normal.fetch = currentNormal;
am.color.fetch = currentColor;
-
+
if (am.vertex.enable) {
am.vertex.resolve();
if (am.vertex.bo || am.vertex.pointer) {
@@ -1362,9 +1371,18 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count)
if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK))
return; // all triangles are culled
+
validate_arrays(c, mode);
+
+ const uint32_t enables = c->rasterizer.state.enables;
+ if (enables & GGL_ENABLE_TMUS)
+ ogles_lock_textures(c);
+
drawArraysPrims[mode](c, first, count);
+ if (enables & GGL_ENABLE_TMUS)
+ ogles_unlock_textures(c);
+
#if VC_CACHE_STATISTICS
c->vc.total = count;
c->vc.dump_stats(mode);
@@ -1409,15 +1427,23 @@ void glDrawElements(
// clear the vertex-cache
c->vc.clear();
validate_arrays(c, mode);
-
+
// if indices are in a buffer object, the pointer is treated as an
// offset in that buffer.
if (c->arrays.element_array_buffer) {
indices = c->arrays.element_array_buffer->data + uintptr_t(indices);
}
+ const uint32_t enables = c->rasterizer.state.enables;
+ if (enables & GGL_ENABLE_TMUS)
+ ogles_lock_textures(c);
+
drawElementsPrims[mode](c, count, indices);
+
+ if (enables & GGL_ENABLE_TMUS)
+ ogles_unlock_textures(c);
+
#if VC_CACHE_STATISTICS
c->vc.total = count;
c->vc.dump_stats(mode);
@@ -1444,7 +1470,7 @@ void glBindBuffer(GLenum target, GLuint buffer)
return;
}
}
- ((target == GL_ARRAY_BUFFER) ?
+ ((target == GL_ARRAY_BUFFER) ?
c->arrays.array_buffer : c->arrays.element_array_buffer) = bo;
}
@@ -1463,7 +1489,7 @@ void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usa
ogles_error(c, GL_INVALID_ENUM);
return;
}
- buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
+ buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
c->arrays.array_buffer : c->arrays.element_array_buffer);
if (bo == 0) {
@@ -1493,7 +1519,7 @@ void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvo
ogles_error(c, GL_INVALID_VALUE);
return;
}
- buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
+ buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
c->arrays.array_buffer : c->arrays.element_array_buffer);
if (bo == 0) {
@@ -1541,7 +1567,7 @@ void glDeleteBuffers(GLsizei n, const GLuint* buffers)
}
}
}
- }
+ }
c->bufferObjectManager->deleteBuffers(n, buffers);
c->bufferObjectManager->recycleTokens(n, buffers);
}
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
new file mode 100644
index 0000000..427e42a
--- /dev/null
+++ b/opengl/libagl/copybit.cpp
@@ -0,0 +1,370 @@
+/*
+**
+** Copyright 2009, 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 <stdio.h>
+
+#include "context.h"
+#include "fp.h"
+#include "state.h"
+#include "matrix.h"
+#include "vertex.h"
+#include "light.h"
+#include "primitives.h"
+#include "texture.h"
+#include "BufferObjectManager.h"
+
+#include "TextureObjectManager.h"
+#include <hardware/gralloc.h>
+#include <hardware/copybit.h>
+#include "gralloc_priv.h"
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static void textureToCopyBitImage(const GGLSurface* surface, int fd, copybit_image_t* img) {
+ img->w = surface->stride;
+ img->h = surface->height;
+ img->format = surface->format;
+ img->offset = 0;
+ img->base = surface->data;
+ img->fd = fd;
+}
+
+struct clipRectRegion : public copybit_region_t {
+ clipRectRegion(ogles_context_t* c) {
+ next = iterate;
+ int x = c->viewport.scissor.x;
+ int y = c->viewport.scissor.y;
+ r.l = x;
+ r.t = y;
+ r.r = x + c->viewport.scissor.w;
+ r.b = y + c->viewport.scissor.h;
+ firstTime = true;
+ }
+private:
+ static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+ clipRectRegion* myself = (clipRectRegion*) self;
+ if (myself->firstTime) {
+ myself->firstTime = false;
+ *rect = myself->r;
+ return 1;
+ }
+ return 0;
+ }
+ mutable copybit_rect_t r;
+ mutable bool firstTime;
+};
+
+static bool supportedCopybitsFormat(int format) {
+ switch (format) {
+ case COPYBIT_FORMAT_RGBA_8888:
+ case COPYBIT_FORMAT_RGB_565:
+ case COPYBIT_FORMAT_BGRA_8888:
+ case COPYBIT_FORMAT_RGBA_5551:
+ case COPYBIT_FORMAT_RGBA_4444:
+ case COPYBIT_FORMAT_YCbCr_422_SP:
+ case COPYBIT_FORMAT_YCbCr_420_SP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool hasAlpha(int format) {
+ switch (format) {
+ case COPYBIT_FORMAT_RGBA_8888:
+ case COPYBIT_FORMAT_BGRA_8888:
+ case COPYBIT_FORMAT_RGBA_5551:
+ case COPYBIT_FORMAT_RGBA_4444:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline int fixedToByte(GGLfixed val) {
+ return (val - (val >> 8)) >> 8;
+}
+
+/**
+ * Performs a quick check of the rendering state. If this function returns
+ * false we cannot use the copybit driver.
+ */
+
+static bool checkContext(ogles_context_t* c) {
+
+ // By convenction copybitQuickCheckContext() has already returned true.
+ // avoid checking the same information again.
+
+ if (c->copybits.blitEngine == NULL
+ || (c->rasterizer.state.enables
+ & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) != 0) {
+ return false;
+ }
+
+ // Note: The drawSurfaceFd is only set for destination
+ // surfaces types that are supported by the hardware and
+ // do not have an alpha channel. So we don't have to re-check that here.
+
+ static const int tmu = 0;
+ texture_unit_t& u(c->textures.tmu[tmu]);
+ EGLTextureObject* textureObject = u.texture;
+
+ if (!supportedCopybitsFormat(textureObject->surface.format)) {
+ return false;
+ }
+ return true;
+}
+
+
+static bool copybit(GLint x, GLint y,
+ GLint w, GLint h,
+ EGLTextureObject* textureObject,
+ const GLint* crop_rect,
+ int transform,
+ ogles_context_t* c)
+{
+ // We assume checkContext has already been called and has already
+ // returned true.
+
+ const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
+
+ y = cbSurface.height - (y + h);
+
+ const GLint Ucr = crop_rect[0];
+ const GLint Vcr = crop_rect[1];
+ const GLint Wcr = crop_rect[2];
+ const GLint Hcr = crop_rect[3];
+
+ int32_t dsdx = (Wcr << 16) / w; // dsdx = ((Wcr/w)/Wt)*Wt
+ int32_t dtdy = ((-Hcr) << 16) / h; // dtdy = -((Hcr/h)/Ht)*Ht
+
+ if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale
+ || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) {
+ // The requested scale is out of the range the hardware
+ // can support.
+ return false;
+ }
+
+ int32_t texelArea = gglMulx(dtdy, dsdx);
+ if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) {
+ // Non-linear filtering on a texture enlargement.
+ return false;
+ }
+
+ if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) {
+ // Non-linear filtering on an texture shrink.
+ return false;
+ }
+
+ const uint32_t enables = c->rasterizer.state.enables;
+ int planeAlpha = 255;
+ static const int tmu = 0;
+ texture_t& tev(c->rasterizer.state.texture[tmu]);
+ bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format);
+ switch (tev.env) {
+
+ case GGL_REPLACE:
+ if (!srcTextureHasAlpha) {
+ planeAlpha = fixedToByte(c->currentColorClamped.a);
+ }
+ break;
+
+ case GGL_MODULATE:
+ if (! (c->currentColorClamped.r == FIXED_ONE
+ && c->currentColorClamped.g == FIXED_ONE
+ && c->currentColorClamped.b == FIXED_ONE)) {
+ return false;
+ }
+ planeAlpha = fixedToByte(c->currentColorClamped.a);
+ break;
+
+ default:
+ // Incompatible texture environment.
+ return false;
+ }
+
+ bool blending = false;
+
+ if ((enables & GGL_ENABLE_BLENDING)
+ && !(c->rasterizer.state.blend.src == GL_ONE
+ && c->rasterizer.state.blend.dst == GL_ZERO)) {
+ // Blending is OK if it is
+ // the exact kind of blending that the copybits hardware supports.
+ // Note: The hardware only supports
+ // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA,
+ // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA.
+ // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case,
+ // because the performance is worth it, even if the results are
+ // not correct.
+ if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA
+ || c->rasterizer.state.blend.src == GL_ONE)
+ && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA
+ && c->rasterizer.state.blend.alpha_separate == 0)) {
+ // Incompatible blend mode.
+ return false;
+ }
+ blending = true;
+ } else {
+ // No blending is OK if we are not using alpha.
+ if (srcTextureHasAlpha || planeAlpha != 255) {
+ // Incompatible alpha
+ return false;
+ }
+ }
+
+ if (srcTextureHasAlpha && planeAlpha != 255) {
+ // Can't do two types of alpha at once.
+ return false;
+ }
+
+ // LOGW("calling copybits");
+
+ copybit_device_t* copybit = c->copybits.blitEngine;
+ copybit_image_t dst;
+ textureToCopyBitImage(&cbSurface, c->copybits.drawSurfaceFd, &dst);
+ copybit_rect_t drect = {x, y, x+w, y+h};
+
+ copybit_image_t src;
+ textureToCopyBitImage(&textureObject->surface, textureObject->copybits_fd,
+ &src);
+ copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
+
+ copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
+ copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
+
+ copybit->set_parameter(copybit, COPYBIT_DITHER,
+ (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
+
+ clipRectRegion it(c);
+ copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+ return true;
+}
+
+/*
+ * Try to draw a triangle fan with copybit, return false if we fail.
+ */
+bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) {
+ if (! checkContext(c)) {
+ return false;
+ }
+
+ c->arrays.compileElements(c, c->vc.vBuffer, 0, 4);
+ // Is the result a screen aligned rectangle?
+ int sx[4];
+ int sy[4];
+ for (int i = 0; i < 4; i++) {
+ GLfixed x = c->vc.vBuffer[i].window.x;
+ GLfixed y = c->vc.vBuffer[i].window.y;
+ if (x < 0 || y < 0 || (x & 0xf) != 0 || (y & 0xf) != 0) {
+ return false;
+ }
+ sx[i] = x >> 4;
+ sy[i] = y >> 4;
+ }
+
+ /*
+ * This is the pattern we're looking for:
+ * (2)--(3)
+ * |\ |
+ * | \ |
+ * | \ |
+ * | \|
+ * (1)--(0)
+ *
+ */
+ int dx[4];
+ int dy[4];
+ for (int i = 0; i < 4; i++) {
+ int i1 = (i + 1) & 3;
+ dx[i] = sx[i] - sx[i1];
+ dy[i] = sy[i] - sy[i1];
+ }
+ if (dx[1] | dx[3] | dy[0] | dy[2]) {
+ return false;
+ }
+ if (dx[0] != -dx[2] || dy[1] != -dy[3]) {
+ return false;
+ }
+
+ int x = sx[1];
+ int y = sy[1];
+ int w = dx[0];
+ int h = dy[3];
+
+ // We expect the texture coordinates to always be the unit square:
+
+ static const GLfixed kExpectedUV[8] = {
+ 0, 0,
+ 0, FIXED_ONE,
+ FIXED_ONE, FIXED_ONE,
+ FIXED_ONE, 0
+ };
+ {
+ const GLfixed* pExpected = &kExpectedUV[0];
+ for (int i = 0; i < 4; i++) {
+ GLfixed u = c->vc.vBuffer[i].texture[0].x;
+ GLfixed v = c->vc.vBuffer[i].texture[0].y;
+ if (u != *pExpected++ || v != *pExpected++) {
+ return false;
+ }
+ }
+ }
+
+ static const int tmu = 0;
+ texture_unit_t& u(c->textures.tmu[tmu]);
+ EGLTextureObject* textureObject = u.texture;
+
+ GLint tWidth = textureObject->surface.width;
+ GLint tHeight = textureObject->surface.height;
+ GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight};
+
+ const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
+ y = cbSurface.height - (y + h);
+
+ return copybit(x, y, w, h, textureObject, crop_rect,
+ COPYBIT_TRANSFORM_ROT_90, c);
+}
+
+/*
+ * Try to drawTexiOESWithCopybit, return false if we fail.
+ */
+
+bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
+ GLint w, GLint h, ogles_context_t* c)
+{
+ // quickly process empty rects
+ if ((w|h) <= 0) {
+ return true;
+ }
+
+ if (! checkContext(c)) {
+ return false;
+ }
+
+ static const int tmu = 0;
+ texture_unit_t& u(c->textures.tmu[tmu]);
+ EGLTextureObject* textureObject = u.texture;
+
+ return copybit(x, y, w, h, textureObject, textureObject->crop_rect,
+ 0, c);
+}
+
+} // namespace android
+
diff --git a/opengl/libagl/copybit.h b/opengl/libagl/copybit.h
new file mode 100644
index 0000000..1888aee
--- /dev/null
+++ b/opengl/libagl/copybit.h
@@ -0,0 +1,75 @@
+/*
+**
+** Copyright 2009, 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.
+*/
+
+#ifndef ANDROID_OPENGLES_COPYBIT_H
+#define ANDROID_OPENGLES_COPYBIT_H
+
+#include <stdlib.h>
+
+#include <GLES/gl.h>
+
+#include "TextureObjectManager.h"
+namespace android {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+
+bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
+ GLint w, GLint h, ogles_context_t* c);
+bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first,
+ GLsizei count);
+
+inline bool copybitQuickCheckContext(ogles_context_t* c) {
+ return c->copybits.drawSurfaceFd >= 0
+ && c->rasterizer.state.enabled_tmu == 1
+ && c->textures.tmu[0].texture->copybits_fd >= 0;
+}
+
+/*
+ * Tries to draw a drawTexiOES using copybit hardware.
+ * Returns true if successful.
+ */
+inline bool drawTexiOESWithCopybit(GLint x, GLint y, GLint z,
+ GLint w, GLint h, ogles_context_t* c) {
+ if (!copybitQuickCheckContext(c)) {
+ return false;
+ }
+
+ return drawTexiOESWithCopybit_impl(x, y, z, w, h, c);
+}
+
+/*
+ * Tries to draw a triangle fan using copybit hardware.
+ * Returns true if successful.
+ */
+inline bool drawTrangleFanWithCopybit(ogles_context_t* c, GLint first,
+ GLsizei count) {
+ /*
+ * We are looking for the glDrawArrays call made by SurfaceFlinger.
+ */
+
+ if (!(copybitQuickCheckContext(c) && first == 0 && count == 4)) {
+ return false;
+ }
+
+ return drawTrangleFanWithCopybit_impl(c, first, count);
+}
+
+
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
+} // namespace android
+
+#endif // ANDROID_OPENGLES_COPYBIT_H
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index c44478d..f50257a 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -15,8 +15,6 @@
** limitations under the License.
*/
-#define LOG_TAG "EGL"
-
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
@@ -41,11 +39,17 @@
#include <pixelflinger/format.h>
#include <pixelflinger/pixelflinger.h>
+#include <private/ui/android_natives_priv.h>
+
#include "context.h"
#include "state.h"
#include "texture.h"
#include "matrix.h"
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include "gralloc_priv.h"
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
#undef NELEM
#define NELEM(x) (sizeof(x)/sizeof(*(x)))
@@ -89,9 +93,9 @@ static GLint getError() {
struct egl_display_t
{
egl_display_t() : type(0), initialized(0) { }
-
+
static egl_display_t& get_display(EGLDisplay dpy);
-
+
static EGLBoolean is_valid(EGLDisplay dpy) {
return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
}
@@ -140,18 +144,20 @@ struct egl_surface_t
egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
virtual ~egl_surface_t();
virtual bool isValid() const = 0;
-
+
virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0;
virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0;
+ virtual void connect() {}
+ virtual void disconnect() {}
virtual EGLint getWidth() const = 0;
virtual EGLint getHeight() const = 0;
- virtual void* getBits() const = 0;
virtual EGLint getHorizontalResolution() const;
virtual EGLint getVerticalResolution() const;
virtual EGLint getRefreshRate() const;
virtual EGLint getSwapBehavior() const;
virtual EGLBoolean swapBuffers();
+ virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
protected:
GGLSurface depth;
};
@@ -185,42 +191,161 @@ EGLint egl_surface_t::getRefreshRate() const {
EGLint egl_surface_t::getSwapBehavior() const {
return EGL_BUFFER_PRESERVED;
}
+EGLBoolean egl_surface_t::setSwapRectangle(
+ EGLint l, EGLint t, EGLint w, EGLint h)
+{
+ return EGL_FALSE;
+}
// ----------------------------------------------------------------------------
-struct egl_window_surface_t : public egl_surface_t
+struct egl_window_surface_v2_t : public egl_surface_t
{
- egl_window_surface_t(
+ egl_window_surface_v2_t(
EGLDisplay dpy, EGLConfig config,
int32_t depthFormat,
- egl_native_window_t* window);
+ android_native_window_t* window);
- ~egl_window_surface_t();
+ ~egl_window_surface_v2_t();
- virtual bool isValid() const { return nativeWindow->magic == 0x600913; }
+ virtual bool isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; }
virtual EGLBoolean swapBuffers();
virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
- virtual EGLint getWidth() const { return nativeWindow->width; }
- virtual EGLint getHeight() const { return nativeWindow->height; }
- virtual void* getBits() const;
+ virtual void connect();
+ virtual void disconnect();
+ virtual EGLint getWidth() const { return buffer->width; }
+ virtual EGLint getHeight() const { return buffer->height; }
virtual EGLint getHorizontalResolution() const;
virtual EGLint getVerticalResolution() const;
virtual EGLint getRefreshRate() const;
virtual EGLint getSwapBehavior() const;
+ virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+
private:
- egl_native_window_t* nativeWindow;
+ status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
+ status_t unlock(android_native_buffer_t* buf);
+ android_native_window_t* nativeWindow;
+ android_native_buffer_t* buffer;
+ android_native_buffer_t* previousBuffer;
+ gralloc_module_t const* module;
+ int width;
+ int height;
+ void* bits;
+ GGLFormat const* pixelFormatTable;
+
+ struct Rect {
+ inline Rect() { };
+ inline Rect(int32_t w, int32_t h)
+ : left(0), top(0), right(w), bottom(h) { }
+ inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
+ : left(l), top(t), right(r), bottom(b) { }
+ Rect& andSelf(const Rect& r) {
+ left = max(left, r.left);
+ top = max(top, r.top);
+ right = min(right, r.right);
+ bottom = min(bottom, r.bottom);
+ return *this;
+ }
+ bool isEmpty() const {
+ return (left>=right || top>=bottom);
+ }
+ void dump(char const* what) {
+ LOGD("%s { %5d, %5d, w=%5d, h=%5d }",
+ what, left, top, right-left, bottom-top);
+ }
+
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+ };
+
+ struct Region {
+ inline Region() : count(0) { }
+ static Region subtract(const Rect& lhs, const Rect& rhs) {
+ Region reg;
+ Rect* storage = reg.storage;
+ if (!lhs.isEmpty()) {
+ if (lhs.top < rhs.top) { // top rect
+ storage->left = lhs.left;
+ storage->top = lhs.top;
+ storage->right = lhs.right;
+ storage->bottom = max(lhs.top, rhs.top);
+ storage++;
+ }
+ if (lhs.left < rhs.left) { // left-side rect
+ storage->left = lhs.left;
+ storage->top = max(lhs.top, rhs.top);
+ storage->right = max(lhs.left, rhs.left);
+ storage->bottom = min(lhs.bottom, rhs.bottom);
+ storage++;
+ }
+ if (lhs.right > rhs.right) { // right-side rect
+ storage->left = min(lhs.right, rhs.right);
+ storage->top = max(lhs.top, rhs.top);
+ storage->right = lhs.right;
+ storage->bottom = min(lhs.bottom, rhs.bottom);
+ storage++;
+ }
+ if (lhs.bottom > rhs.bottom) { // bottom rect
+ storage->left = lhs.left;
+ storage->top = min(lhs.bottom, rhs.bottom);
+ storage->right = lhs.right;
+ storage->bottom = lhs.bottom;
+ storage++;
+ }
+ reg.count = storage - reg.storage;
+ }
+ return reg;
+ }
+ bool isEmpty() const {
+ return count<=0;
+ }
+ ssize_t getRects(Rect const* * rects) const {
+ *rects = storage;
+ return count;
+ }
+ private:
+ Rect storage[4];
+ ssize_t count;
+ };
+
+ void copyBlt(
+ android_native_buffer_t* dst, void* dst_vaddr,
+ android_native_buffer_t* src, void const* src_vaddr,
+ const Rect* reg, ssize_t count);
+
+ Rect dirtyRegion;
+ Rect oldDirtyRegion;
};
-egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy,
+egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
EGLConfig config,
int32_t depthFormat,
- egl_native_window_t* window)
- : egl_surface_t(dpy, config, depthFormat), nativeWindow(window)
+ android_native_window_t* window)
+ : egl_surface_t(dpy, config, depthFormat),
+ nativeWindow(window), buffer(0), previousBuffer(0), module(0),
+ bits(NULL)
{
+ hw_module_t const* pModule;
+ hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
+ module = reinterpret_cast<gralloc_module_t const*>(pModule);
+
+ pixelFormatTable = gglGetPixelFormatTable();
+
+ // keep a reference on the window
+ nativeWindow->common.incRef(&nativeWindow->common);
+
+ // dequeue a buffer
+ nativeWindow->dequeueBuffer(nativeWindow, &buffer);
+
+ // allocate a corresponding depth-buffer
+ width = buffer->width;
+ height = buffer->height;
if (depthFormat) {
- depth.width = window->width;
- depth.height = window->height;
+ depth.width = width;
+ depth.height = height;
depth.stride = depth.width; // use the width here
depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
if (depth.data == 0) {
@@ -228,76 +353,258 @@ egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy,
return;
}
}
- nativeWindow->incRef(nativeWindow);
+
+ // keep a reference on the buffer
+ buffer->common.incRef(&buffer->common);
+}
+
+egl_window_surface_v2_t::~egl_window_surface_v2_t() {
+ if (buffer) {
+ buffer->common.decRef(&buffer->common);
+ }
+ if (previousBuffer) {
+ previousBuffer->common.decRef(&previousBuffer->common);
+ }
+ nativeWindow->common.decRef(&nativeWindow->common);
+}
+
+void egl_window_surface_v2_t::connect()
+{
+ // Lock the buffer
+ nativeWindow->lockBuffer(nativeWindow, buffer);
+ // pin the buffer down
+ if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+ LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
+ buffer, buffer->width, buffer->height);
+ setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
+ // FIXME: we should make sure we're not accessing the buffer anymore
+ }
+}
+
+void egl_window_surface_v2_t::disconnect()
+{
+ if (buffer) {
+ bits = NULL;
+ unlock(buffer);
+ }
+}
+
+status_t egl_window_surface_v2_t::lock(
+ android_native_buffer_t* buf, int usage, void** vaddr)
+{
+ int err = module->lock(module, buf->handle,
+ usage, 0, 0, buf->width, buf->height, vaddr);
+ return err;
+}
+
+status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
+{
+ int err = module->unlock(module, buf->handle);
+ return err;
}
-egl_window_surface_t::~egl_window_surface_t() {
- nativeWindow->decRef(nativeWindow);
+
+void egl_window_surface_v2_t::copyBlt(
+ android_native_buffer_t* dst, void* dst_vaddr,
+ android_native_buffer_t* src, void const* src_vaddr,
+ const Rect* reg, ssize_t count)
+{
+ // FIXME: use copybit if possible
+ // NOTE: dst and src must be the same format
+
+ Rect r;
+ const size_t bpp = pixelFormatTable[src->format].size;
+ const size_t dbpr = dst->stride * bpp;
+ const size_t sbpr = src->stride * bpp;
+
+ uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
+ uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
+
+ for (int i= 0 ; i<count ; i++) {
+ const Rect& r(reg[i]);
+ ssize_t w = r.right - r.left;
+ ssize_t h = r.bottom - r.top;
+ if (w <= 0 || h<=0) continue;
+ size_t size = w * bpp;
+ uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+ uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
+ if (dbpr==sbpr && size==sbpr) {
+ size *= h;
+ h = 1;
+ }
+ do {
+ memcpy(d, s, size);
+ d += dbpr;
+ s += sbpr;
+ } while (--h > 0);
+ }
}
-EGLBoolean egl_window_surface_t::swapBuffers()
+EGLBoolean egl_window_surface_v2_t::swapBuffers()
{
- uint32_t flags = nativeWindow->swapBuffers(nativeWindow);
- if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) {
+ /*
+ * Handle eglSetSwapRectangleANDROID()
+ * We copyback from the front buffer
+ */
+ if (!dirtyRegion.isEmpty()) {
+ dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
+ if (previousBuffer) {
+ const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
+ if (!copyBack.isEmpty()) {
+ Rect const* list;
+ ssize_t count = copyBack.getRects(&list);
+ // copy from previousBuffer to buffer
+ void* prevBits;
+ if (lock(previousBuffer,
+ GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR)
+ {
+ copyBlt(buffer, bits, previousBuffer, prevBits, list, count);
+ unlock(previousBuffer);
+ }
+ }
+ }
+ oldDirtyRegion = dirtyRegion;
+ }
+
+ if (previousBuffer) {
+ previousBuffer->common.decRef(&previousBuffer->common);
+ previousBuffer = 0;
+ }
+
+ unlock(buffer);
+ previousBuffer = buffer;
+ nativeWindow->queueBuffer(nativeWindow, buffer);
+ buffer = 0;
+
+ // dequeue a new buffer
+ nativeWindow->dequeueBuffer(nativeWindow, &buffer);
+
+ // TODO: lockBuffer should rather be executed when the very first
+ // direct rendering occurs.
+ nativeWindow->lockBuffer(nativeWindow, buffer);
+
+ // reallocate the depth-buffer if needed
+ if ((width != buffer->width) || (height != buffer->height)) {
// TODO: we probably should reset the swap rect here
// if the window size has changed
+ width = buffer->width;
+ height = buffer->height;
if (depth.data) {
free(depth.data);
- depth.width = nativeWindow->width;
- depth.height = nativeWindow->height;
- depth.stride = nativeWindow->stride;
+ depth.width = width;
+ depth.height = height;
+ depth.stride = buffer->stride;
depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
if (depth.data == 0) {
- setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ setError(EGL_BAD_ALLOC, EGL_FALSE);
return EGL_FALSE;
}
}
}
+
+ // keep a reference on the buffer
+ buffer->common.incRef(&buffer->common);
+
+ // finally pin the buffer down
+ if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+ LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
+ buffer, buffer->width, buffer->height);
+ setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
+ // FIXME: we should make sure we're not accessing the buffer anymore
+ }
+
return EGL_TRUE;
}
-EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl)
+EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
+ EGLint l, EGLint t, EGLint w, EGLint h)
+{
+ dirtyRegion = Rect(l, t, l+w, t+h);
+ return EGL_TRUE;
+}
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+
+static bool supportedCopybitsDestinationFormat(int format) {
+ // Hardware supported and no destination alpha
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ return true;
+ default:
+ return false;
+ }
+}
+#endif
+
+EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl)
{
GGLSurface buffer;
buffer.version = sizeof(GGLSurface);
- buffer.width = nativeWindow->width;
- buffer.height = nativeWindow->height;
- buffer.stride = nativeWindow->stride;
- buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset;
- buffer.format = nativeWindow->format;
+ buffer.width = this->buffer->width;
+ buffer.height = this->buffer->height;
+ buffer.stride = this->buffer->stride;
+ buffer.data = (GGLubyte*)bits;
+ buffer.format = this->buffer->format;
gl->rasterizer.procs.colorBuffer(gl, &buffer);
if (depth.data != gl->rasterizer.state.buffers.depth.data)
gl->rasterizer.procs.depthBuffer(gl, &depth);
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ gl->copybits.drawSurfaceFd = -1;
+ if (supportedCopybitsDestinationFormat(buffer.format)) {
+ buffer_handle_t handle = this->buffer->handle;
+ if (handle != NULL) {
+ private_handle_t* hand = private_handle_t::dynamicCast(handle);
+ if (hand != NULL) {
+ if (hand->usesPhysicallyContiguousMemory()) {
+ gl->copybits.drawSurfaceFd = hand->fd;
+ }
+ }
+ }
+ }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
return EGL_TRUE;
}
-EGLBoolean egl_window_surface_t::bindReadSurface(ogles_context_t* gl)
+EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl)
{
GGLSurface buffer;
buffer.version = sizeof(GGLSurface);
- buffer.width = nativeWindow->width;
- buffer.height = nativeWindow->height;
- buffer.stride = nativeWindow->stride;
- buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset;
- buffer.format = nativeWindow->format;
+ buffer.width = this->buffer->width;
+ buffer.height = this->buffer->height;
+ buffer.stride = this->buffer->stride;
+ buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
+ buffer.format = this->buffer->format;
gl->rasterizer.procs.readBuffer(gl, &buffer);
return EGL_TRUE;
}
-void* egl_window_surface_t::getBits() const {
- return (GGLubyte*)nativeWindow->base + nativeWindow->offset;
-}
-EGLint egl_window_surface_t::getHorizontalResolution() const {
+EGLint egl_window_surface_v2_t::getHorizontalResolution() const {
return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
}
-EGLint egl_window_surface_t::getVerticalResolution() const {
+EGLint egl_window_surface_v2_t::getVerticalResolution() const {
return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
}
-EGLint egl_window_surface_t::getRefreshRate() const {
- return (nativeWindow->fps * EGL_DISPLAY_SCALING);
+EGLint egl_window_surface_v2_t::getRefreshRate() const {
+ return (60 * EGL_DISPLAY_SCALING); // FIXME
}
-EGLint egl_window_surface_t::getSwapBehavior() const {
- uint32_t flags = nativeWindow->flags;
- if (flags & EGL_NATIVES_FLAG_DESTROY_BACKBUFFER)
- return EGL_BUFFER_DESTROYED;
- return EGL_BUFFER_PRESERVED;
+EGLint egl_window_surface_v2_t::getSwapBehavior() const
+{
+ /*
+ * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
+ * the content of the swapped buffer.
+ *
+ * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
+ *
+ * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
+ * only applies to the area specified by eglSetSwapRectangleANDROID(), that
+ * is, everything outside of this area is preserved.
+ *
+ * This implementation of EGL assumes the later case.
+ *
+ */
+
+ return EGL_BUFFER_DESTROYED;
}
// ----------------------------------------------------------------------------
@@ -311,12 +618,11 @@ struct egl_pixmap_surface_t : public egl_surface_t
virtual ~egl_pixmap_surface_t() { }
- virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }
+ virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }
virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
virtual EGLint getWidth() const { return nativePixmap.width; }
virtual EGLint getHeight() const { return nativePixmap.height; }
- virtual void* getBits() const { return nativePixmap.data; }
private:
egl_native_pixmap_t nativePixmap;
};
@@ -347,7 +653,7 @@ EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl)
buffer.stride = nativePixmap.stride;
buffer.data = nativePixmap.data;
buffer.format = nativePixmap.format;
-
+
gl->rasterizer.procs.colorBuffer(gl, &buffer);
if (depth.data != gl->rasterizer.state.buffers.depth.data)
gl->rasterizer.procs.depthBuffer(gl, &depth);
@@ -376,12 +682,11 @@ struct egl_pbuffer_surface_t : public egl_surface_t
virtual ~egl_pbuffer_surface_t();
- virtual bool isValid() const { return pbuffer.data != 0; }
+ virtual bool isValid() const { return pbuffer.data != 0; }
virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
virtual EGLint getWidth() const { return pbuffer.width; }
virtual EGLint getHeight() const { return pbuffer.height; }
- virtual void* getBits() const { return pbuffer.data; }
private:
GGLSurface pbuffer;
};
@@ -407,7 +712,7 @@ egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
pbuffer.stride = w;
pbuffer.data = (GGLubyte*)malloc(size);
pbuffer.format = f;
-
+
if (depthFormat) {
depth.width = pbuffer.width;
depth.height = pbuffer.height;
@@ -468,7 +773,12 @@ struct config_management_t {
static char const * const gVendorString = "Google Inc.";
static char const * const gVersionString = "1.2 Android Driver";
static char const * const gClientApiString = "OpenGL ES";
-static char const * const gExtensionsString = "";
+static char const * const gExtensionsString =
+ "EGL_KHR_image_base "
+ // "KHR_image_pixmap "
+ "EGL_ANDROID_image_native_buffer "
+ "EGL_ANDROID_swap_rectangle "
+ ;
// ----------------------------------------------------------------------------
@@ -496,6 +806,10 @@ static const extention_map_t gExtentionMap[] = {
(__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
{ "glQueryMatrixxOES",
(__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
+ { "glEGLImageTargetTexture2DOES",
+ (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
+ { "glEGLImageTargetRenderbufferStorageOES",
+ (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
{ "glClipPlanef",
(__eglMustCastToProperFunctionPointerType)&glClipPlanef },
{ "glClipPlanex",
@@ -512,7 +826,7 @@ static const extention_map_t gExtentionMap[] = {
(__eglMustCastToProperFunctionPointerType)&glGenBuffers },
};
-/*
+/*
* In the lists below, attributes names MUST be sorted.
* Additionally, all configs must be sorted according to
* the EGL specification.
@@ -523,7 +837,7 @@ static config_pair_t const config_base_attribute_list[] = {
{ EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG },
{ EGL_LEVEL, 0 },
{ EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS },
- { EGL_MAX_PBUFFER_PIXELS,
+ { EGL_MAX_PBUFFER_PIXELS,
GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS },
{ EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS },
{ EGL_NATIVE_RENDERABLE, EGL_TRUE },
@@ -660,9 +974,9 @@ static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
{
while (first <= last) {
int mid = (first + last) / 2;
- if (key > sortedArray[mid].key) {
+ if (key > sortedArray[mid].key) {
first = mid + 1;
- } else if (key < sortedArray[mid].key) {
+ } else if (key < sortedArray[mid].key) {
last = mid - 1;
} else {
return mid;
@@ -674,13 +988,13 @@ static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
static int isAttributeMatching(int i, EGLint attr, EGLint val)
{
// look for the attribute in all of our configs
- config_pair_t const* configFound = gConfigs[i].array;
+ config_pair_t const* configFound = gConfigs[i].array;
int index = binarySearch<config_pair_t>(
gConfigs[i].array,
0, gConfigs[i].size-1,
attr);
if (index < 0) {
- configFound = config_base_attribute_list;
+ configFound = config_base_attribute_list;
index = binarySearch<config_pair_t>(
config_base_attribute_list,
0, NELEM(config_base_attribute_list)-1,
@@ -794,28 +1108,28 @@ static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
int32_t depthFormat;
int32_t pixelFormat;
switch(configID) {
- case 0:
- pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+ case 0:
+ pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
depthFormat = 0;
break;
case 1:
- pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+ pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
case 2:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
depthFormat = 0;
break;
case 3:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
case 4:
- pixelFormat = GGL_PIXEL_FORMAT_A_8;
+ pixelFormat = GGL_PIXEL_FORMAT_A_8;
depthFormat = 0;
break;
case 5:
- pixelFormat = GGL_PIXEL_FORMAT_A_8;
+ pixelFormat = GGL_PIXEL_FORMAT_A_8;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
default:
@@ -828,9 +1142,9 @@ static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
//if (EGLint(info.format) != pixelFormat)
// return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
- egl_surface_t* surface =
- new egl_window_surface_t(dpy, config, depthFormat,
- static_cast<egl_native_window_t*>(window));
+ egl_surface_t* surface;
+ surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
+ static_cast<android_native_window_t*>(window));
if (!surface->isValid()) {
// there was a problem in the ctor, the error
@@ -863,28 +1177,28 @@ static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
int32_t depthFormat;
int32_t pixelFormat;
switch(configID) {
- case 0:
- pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+ case 0:
+ pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
depthFormat = 0;
break;
case 1:
- pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+ pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
case 2:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
depthFormat = 0;
break;
case 3:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
case 4:
- pixelFormat = GGL_PIXEL_FORMAT_A_8;
+ pixelFormat = GGL_PIXEL_FORMAT_A_8;
depthFormat = 0;
break;
case 5:
- pixelFormat = GGL_PIXEL_FORMAT_A_8;
+ pixelFormat = GGL_PIXEL_FORMAT_A_8;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
default:
@@ -916,10 +1230,10 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
EGLint surfaceType;
if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
return EGL_FALSE;
-
+
if (!(surfaceType & EGL_PBUFFER_BIT))
return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
-
+
EGLint configID;
if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
return EGL_FALSE;
@@ -927,28 +1241,28 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
int32_t depthFormat;
int32_t pixelFormat;
switch(configID) {
- case 0:
- pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+ case 0:
+ pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
depthFormat = 0;
break;
case 1:
- pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+ pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
case 2:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
depthFormat = 0;
break;
case 3:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
case 4:
- pixelFormat = GGL_PIXEL_FORMAT_A_8;
+ pixelFormat = GGL_PIXEL_FORMAT_A_8;
depthFormat = 0;
break;
case 5:
- pixelFormat = GGL_PIXEL_FORMAT_A_8;
+ pixelFormat = GGL_PIXEL_FORMAT_A_8;
depthFormat = GGL_PIXEL_FORMAT_Z_16;
break;
default:
@@ -1001,7 +1315,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display)
egl_display_t& d = egl_display_t::get_display(dpy);
d.type = display;
return dpy;
- }
+ }
return EGL_NO_DISPLAY;
}
@@ -1009,10 +1323,10 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
if (egl_display_t::is_valid(dpy) == EGL_FALSE)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
+
EGLBoolean res = EGL_TRUE;
egl_display_t& d = egl_display_t::get_display(dpy);
-
+
if (android_atomic_inc(&d.initialized) == 0) {
// initialize stuff here if needed
//pthread_mutex_lock(&gInitMutex);
@@ -1080,7 +1394,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
*num_config = 0;
return EGL_TRUE;
}
-
+
int numAttributes = 0;
int numConfigs = NELEM(gConfigs);
uint32_t possibleMatch = (1<<numConfigs)-1;
@@ -1161,7 +1475,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
{
return createWindowSurface(dpy, config, window, attrib_list);
}
-
+
EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
NativePixmapType pixmap,
const EGLint *attrib_list)
@@ -1174,7 +1488,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
{
return createPbufferSurface(dpy, config, attrib_list);
}
-
+
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
{
if (egl_display_t::is_valid(dpy) == EGL_FALSE)
@@ -1185,6 +1499,11 @@ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (surface->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ if (surface->ctx) {
+ // FIXME: this surface is current check what the spec says
+ surface->disconnect();
+ surface->ctx = 0;
+ }
delete surface;
}
return EGL_TRUE;
@@ -1244,7 +1563,7 @@ EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
*value = (wr * EGL_DISPLAY_SCALING) / hr;
} break;
case EGL_SWAP_BEHAVIOR:
- *value = surface->getSwapBehavior();
+ *value = surface->getSwapBehavior();
break;
default:
ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
@@ -1294,7 +1613,7 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
}
EGLContext current_ctx = EGL_NO_CONTEXT;
-
+
if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
return setError(EGL_BAD_MATCH, EGL_FALSE);
@@ -1310,21 +1629,28 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
egl_surface_t* r = (egl_surface_t*)read;
if ((d && d->ctx && d->ctx != ctx) ||
(r && r->ctx && r->ctx != ctx)) {
- // once of the surface is bound to a context in another thread
+ // one of the surface is bound to a context in another thread
return setError(EGL_BAD_ACCESS, EGL_FALSE);
}
}
- // TODO: call connect / disconnect on the surface
-
ogles_context_t* gl = (ogles_context_t*)ctx;
if (makeCurrent(gl) == 0) {
if (ctx) {
egl_context_t* c = egl_context_t::context(ctx);
egl_surface_t* d = (egl_surface_t*)draw;
egl_surface_t* r = (egl_surface_t*)read;
- c->read = read;
+
+ if (c->draw) {
+ reinterpret_cast<egl_surface_t*>(c->draw)->disconnect();
+ }
+ if (c->read) {
+ // FIXME: unlock/disconnect the read surface too
+ }
+
c->draw = draw;
+ c->read = read;
+
if (c->flags & egl_context_t::NEVER_CURRENT) {
c->flags &= ~egl_context_t::NEVER_CURRENT;
GLint w = 0;
@@ -1338,10 +1664,12 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
ogles_scissor(gl, 0, 0, w, h);
}
if (d) {
+ d->connect();
d->ctx = ctx;
d->bindDrawSurface(gl);
}
if (r) {
+ // FIXME: lock/connect the read surface too
r->ctx = ctx;
r->bindReadSurface(gl);
}
@@ -1352,8 +1680,14 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
egl_context_t* c = egl_context_t::context(current_ctx);
egl_surface_t* d = (egl_surface_t*)c->draw;
egl_surface_t* r = (egl_surface_t*)c->read;
- if (d) d->ctx = EGL_NO_CONTEXT;
- if (r) r->ctx = EGL_NO_CONTEXT;
+ if (d) {
+ d->ctx = EGL_NO_CONTEXT;
+ d->disconnect();
+ }
+ if (r) {
+ r->ctx = EGL_NO_CONTEXT;
+ // FIXME: unlock/disconnect the read surface too
+ }
}
}
return EGL_TRUE;
@@ -1425,7 +1759,7 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
if (egl_display_t::is_valid(dpy) == EGL_FALSE)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
+
egl_surface_t* d = static_cast<egl_surface_t*>(draw);
if (d->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1558,7 +1892,7 @@ EGLSurface eglCreatePbufferFromClientBuffer(
}
// ----------------------------------------------------------------------------
-// Android extensions
+// EGL_EGLEXT_VERSION 3
// ----------------------------------------------------------------------------
void (*eglGetProcAddress (const char *procname))()
@@ -1571,3 +1905,80 @@ void (*eglGetProcAddress (const char *procname))()
}
return NULL;
}
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+ const EGLint *attrib_list)
+{
+ EGLBoolean result = EGL_FALSE;
+ return result;
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+{
+ EGLBoolean result = EGL_FALSE;
+ return result;
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+ EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+ return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
+ }
+ if (ctx != EGL_NO_CONTEXT) {
+ return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+ }
+ if (target != EGL_NATIVE_BUFFER_ANDROID) {
+ return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+ }
+
+ android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
+
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+ return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+ if (native_buffer->common.version != sizeof(android_native_buffer_t))
+ return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+ native_buffer->common.incRef(&native_buffer->common);
+ return (EGLImageKHR)native_buffer;
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ }
+
+ android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
+
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+ if (native_buffer->common.version != sizeof(android_native_buffer_t))
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+ native_buffer->common.decRef(&native_buffer->common);
+
+ return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// ANDROID extensions
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
+ EGLint left, EGLint top, EGLint width, EGLint height)
+{
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+ egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+ if (d->dpy != dpy)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+ // post the surface
+ d->setSwapRectangle(left, top, width, height);
+
+ return EGL_TRUE;
+}
diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp
index 5cbabea..a00f779 100644
--- a/opengl/libagl/state.cpp
+++ b/opengl/libagl/state.cpp
@@ -2,16 +2,16 @@
**
** 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
+** 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
+** 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
+** 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.
*/
@@ -28,12 +28,16 @@
#include "BufferObjectManager.h"
#include "TextureObjectManager.h"
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include <hardware/copybit.h>
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
namespace android {
// ----------------------------------------------------------------------------
static char const * const gVendorString = "Android";
-static char const * const gRendererString = "Android PixelFlinger 1.0";
+static char const * const gRendererString = "Android PixelFlinger 1.1";
static char const * const gVersionString = "OpenGL ES-CM 1.0";
static char const * const gExtensionsString =
"GL_OES_byte_coordinates " // OK
@@ -46,9 +50,9 @@ static char const * const gExtensionsString =
"GL_OES_query_matrix " // OK
// "GL_OES_point_size_array " // TODO
// "GL_OES_point_sprite " // TODO
+ "GL_OES_EGL_image " // OK
"GL_ARB_texture_compression " // OK
"GL_ARB_texture_non_power_of_two " // OK
- "GL_ANDROID_direct_texture " // OK
"GL_ANDROID_user_clip_plane " // OK
"GL_ANDROID_vertex_buffer_object " // OK
"GL_ANDROID_generate_mipmap " // OK
@@ -62,13 +66,13 @@ static char const * const gExtensionsString =
ogles_context_t *ogles_init(size_t extra)
{
void* const base = malloc(extra + sizeof(ogles_context_t) + 32);
- if (!base) return 0;
+ if (!base) return 0;
ogles_context_t *c =
(ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL);
memset(c, 0, sizeof(ogles_context_t));
ggl_init_context(&(c->rasterizer));
-
+
// XXX: this should be passed as an argument
sp<EGLSurfaceManager> smgr(new EGLSurfaceManager());
c->surfaceManager = smgr.get();
@@ -87,13 +91,42 @@ ogles_context_t *ogles_init(size_t extra)
c->rasterizer.base = base;
c->point.size = TRI_ONE;
c->line.width = TRI_ONE;
-
+
// in OpenGL, writing to the depth buffer is enabled by default.
c->rasterizer.procs.depthMask(c, 1);
-
+
// OpenGL enables dithering by default
c->rasterizer.procs.enable(c, GL_DITHER);
+ c->copybits.blitEngine = NULL;
+ c->copybits.minScale = 0;
+ c->copybits.maxScale = 0;
+ c->copybits.drawSurfaceFd = -1;
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ hw_module_t const* module;
+ if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+ struct copybit_device_t* copyBits;
+ if (copybit_open(module, &copyBits) == 0) {
+ c->copybits.blitEngine = copyBits;
+ {
+ int minLim = copyBits->get(copyBits,
+ COPYBIT_MINIFICATION_LIMIT);
+ if (minLim != -EINVAL && minLim > 0) {
+ c->copybits.minScale = (1 << 16) / minLim;
+ }
+ }
+ {
+ int magLim = copyBits->get(copyBits,
+ COPYBIT_MAGNIFICATION_LIMIT);
+ if (magLim != -EINVAL && magLim > 0) {
+ c->copybits.maxScale = min(32*1024-1, magLim) << 16;
+ }
+ }
+ }
+ }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
return c;
}
@@ -107,7 +140,12 @@ void ogles_uninit(ogles_context_t* c)
c->surfaceManager->decStrong(c);
c->bufferObjectManager->decStrong(c);
ggl_uninit_context(&(c->rasterizer));
- free(c->rasterizer.base);
+ free(c->rasterizer.base);
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ if (c->copybits.blitEngine != NULL) {
+ copybit_close((struct copybit_device_t*) c->copybits.blitEngine);
+ }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
}
void _ogles_error(ogles_context_t* c, GLenum error)
@@ -188,7 +226,7 @@ static void enable_disable(ogles_context_t* c, GLenum cap, int enabled)
// these need to fall through into the rasterizer
c->rasterizer.procs.enableDisable(c, cap, enabled);
break;
-
+
case GL_MULTISAMPLE:
case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_ALPHA_TO_ONE:
@@ -281,7 +319,7 @@ void glHint(GLenum target, GLenum mode)
case GL_LINE_SMOOTH_HINT:
break;
case GL_POINT_SMOOTH_HINT:
- c->rasterizer.procs.enableDisable(c,
+ c->rasterizer.procs.enableDisable(c,
GGL_POINT_SMOOTH_NICE, mode==GL_NICEST);
break;
case GL_PERSPECTIVE_CORRECTION_HINT:
@@ -323,7 +361,7 @@ GLenum glGetError()
c->error = 0;
return ret;
}
-
+
if (c->rasterizer.error) {
const GLenum ret(c->rasterizer.error);
c->rasterizer.error = 0;
@@ -362,25 +400,25 @@ void glGetIntegerv(GLenum pname, GLint *params)
int index = c->rasterizer.state.buffers.color.format;
GGLFormat const * formats = gglGetPixelFormatTable();
params[0] = formats[index].ah - formats[index].al;
- break;
+ break;
}
case GL_RED_BITS: {
int index = c->rasterizer.state.buffers.color.format;
GGLFormat const * formats = gglGetPixelFormatTable();
params[0] = formats[index].rh - formats[index].rl;
- break;
+ break;
}
case GL_GREEN_BITS: {
int index = c->rasterizer.state.buffers.color.format;
GGLFormat const * formats = gglGetPixelFormatTable();
params[0] = formats[index].gh - formats[index].gl;
- break;
+ break;
}
case GL_BLUE_BITS: {
int index = c->rasterizer.state.buffers.color.format;
GGLFormat const * formats = gglGetPixelFormatTable();
params[0] = formats[index].bh - formats[index].bl;
- break;
+ break;
}
case GL_COMPRESSED_TEXTURE_FORMATS:
params[ 0] = GL_PALETTE4_RGB8_OES;
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index b6f534b..d675107 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -2,16 +2,16 @@
**
** 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
+** 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
+** 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
+** 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.
*/
@@ -23,6 +23,13 @@
#include "texture.h"
#include "TextureObjectManager.h"
+#include <private/ui/android_natives_priv.h>
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include "copybit.h"
+#include "gralloc_priv.h"
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
namespace android {
// ----------------------------------------------------------------------------
@@ -48,7 +55,7 @@ void ogles_init_texture(ogles_context_t* c)
// 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);
@@ -96,7 +103,7 @@ void validate_tmu(ogles_context_t* c, int i)
}
}
-void ogles_validate_texture_impl(ogles_context_t* c)
+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)
@@ -110,6 +117,66 @@ 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]);
+ android_native_buffer_t* native_buffer = u.texture->buffer;
+ if (native_buffer) {
+ c->rasterizer.procs.activeTexture(c, i);
+ hw_module_t const* pModule;
+ if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
+ continue;
+
+ gralloc_module_t const* module =
+ reinterpret_cast<gralloc_module_t const*>(pModule);
+
+ void* vaddr;
+ int err = module->lock(module, native_buffer->handle,
+ GRALLOC_USAGE_SW_READ_OFTEN,
+ 0, 0, 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]);
+ android_native_buffer_t* native_buffer = u.texture->buffer;
+ if (native_buffer) {
+ c->rasterizer.procs.activeTexture(c, i);
+ hw_module_t const* pModule;
+ if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
+ continue;
+
+ gralloc_module_t const* module =
+ reinterpret_cast<gralloc_module_t const*>(pModule);
+
+ module->unlock(module, 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 -
@@ -255,7 +322,7 @@ sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c)
u.texture->decStrong(c);
if (name == 0) {
- // 0 is our local texture object, not shared with anyone.
+ // 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;
@@ -273,7 +340,7 @@ sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c)
u.texture = tex.get();
u.texture->incStrong(c);
u.name = name;
- invalidate_texture(c, active);
+ invalidate_texture(c, active);
return tex;
}
@@ -282,7 +349,7 @@ void bindTextureTmu(
{
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)
@@ -310,7 +377,7 @@ int createTextureSurface(ogles_context_t* c,
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;
@@ -530,8 +597,8 @@ static void texParameterx(
ogles_error(c, GL_INVALID_ENUM);
return;
}
-
- EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;
+
+ EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;
switch (pname) {
case GL_TEXTURE_WRAP_S:
if ((param == GL_REPEAT) ||
@@ -581,13 +648,12 @@ invalid_enum:
}
-static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
+
+static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
ogles_context_t* c)
{
- // quickly reject empty rects
- if ((w|h) <= 0)
- return;
-
+ ogles_lock_textures(c);
+
const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
y = gglIntToFixed(cbSurface.height) - (y + h);
w >>= FIXED_BITS;
@@ -610,7 +676,7 @@ static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP);
u.dirty = 0xFF; // XXX: should be more subtle
- EGLTextureObject* textureObject = u.texture;
+ 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;
@@ -641,11 +707,30 @@ static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
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,
+ 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)
+{
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ if (drawTexiOESWithCopybit(gglFixedToIntRound(x),
+ gglFixedToIntRound(y), gglFixedToIntRound(z),
+ gglFixedToIntRound(w), gglFixedToIntRound(h), c)) {
+ return;
+ }
+#else
+ // quickly reject empty rects
+ if ((w|h) <= 0)
+ return;
+#endif
+ drawTexxOESImp(x, y, z, w, h, c);
}
static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c)
@@ -656,14 +741,21 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte
// which is a lot faster.
if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ if (drawTexiOESWithCopybit(x, y, z, w, h, c)) {
+ return;
+ }
+#endif
const int tmu = 0;
texture_unit_t& u(c->textures.tmu[tmu]);
- EGLTextureObject* textureObject = u.texture;
+ EGLTextureObject* textureObject = u.texture;
const GLint Wcr = textureObject->crop_rect[2];
const GLint Hcr = textureObject->crop_rect[3];
if ((w == Wcr) && (h == -Hcr)) {
+#ifndef LIBAGL_USE_GRALLOC_COPYBITS
if ((w|h) <= 0) return; // quickly reject empty rects
+#endif
if (u.dirty) {
c->rasterizer.procs.activeTexture(c, tmu);
@@ -679,14 +771,14 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte
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)) {
@@ -694,7 +786,9 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte
// 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;
@@ -706,12 +800,15 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte
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:
- drawTexxOES(
+ drawTexxOESImp(
gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z),
gglIntToFixed(w), gglIntToFixed(h),
c);
@@ -749,7 +846,7 @@ void glBindTexture(GLenum target, GLuint texture)
}
// Bind or create a texture
- sp<EGLTextureObject> tex;
+ sp<EGLTextureObject> tex;
if (texture == 0) {
// 0 is our local texture object
tex = c->textures.defaultTexture;
@@ -837,7 +934,7 @@ void glPixelStorei(GLenum pname, GLint param)
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;
@@ -945,7 +1042,7 @@ void glCompressedTexImage2D(
}
// "uncompress" the texture since pixelflinger doesn't support
- // any compressed texture format natively.
+ // any compressed texture format natively.
GLenum format;
GLenum type;
switch (internalformat) {
@@ -1009,7 +1106,7 @@ void glTexImage2D(
GLenum format, GLenum type, const GLvoid *pixels)
{
ogles_context_t* c = ogles_context_t::get();
- if (target != GL_TEXTURE_2D && target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
+ if (target != GL_TEXTURE_2D) {
ogles_error(c, GL_INVALID_ENUM);
return;
}
@@ -1017,7 +1114,7 @@ void glTexImage2D(
ogles_error(c, GL_INVALID_VALUE);
return;
}
- if (format != internalformat) {
+ if (format != (GLenum)internalformat) {
ogles_error(c, GL_INVALID_OPERATION);
return;
}
@@ -1027,16 +1124,10 @@ void glTexImage2D(
int32_t size = 0;
GGLSurface* surface = 0;
- if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
- int error = createTextureSurface(c, &surface, &size,
- level, format, type, width, height);
- if (error) {
- ogles_error(c, error);
- return;
- }
- } else if (pixels == 0 || level != 0) {
- // pixel can't be null for direct texture
- ogles_error(c, GL_INVALID_OPERATION);
+ int error = createTextureSurface(c, &surface, &size,
+ level, format, type, width, height);
+ if (error) {
+ ogles_error(c, error);
return;
}
@@ -1057,18 +1148,12 @@ void glTexImage2D(
userSurface.compressedFormat = 0;
userSurface.data = (GLubyte*)pixels;
- if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
- int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height);
- if (err) {
- ogles_error(c, err);
- return;
- }
- generateMipmap(c, level);
- } else {
- // bind it to the texture unit
- sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
- tex->setSurface(&userSurface);
+ int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height);
+ if (err) {
+ ogles_error(c, err);
+ return;
}
+ generateMipmap(c, level);
}
}
@@ -1143,7 +1228,7 @@ void glTexSubImage2D(
int err = copyPixels(c,
surface, xoffset, yoffset,
- userSurface, 0, 0, width, height);
+ userSurface, 0, 0, width, height);
if (err) {
ogles_error(c, err);
return;
@@ -1196,7 +1281,7 @@ void glCopyTexImage2D(
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE:
type = GL_UNSIGNED_BYTE;
- break;
+ break;
}
// figure out the format to use for the new texture
@@ -1206,7 +1291,7 @@ void glCopyTexImage2D(
case GGL_PIXEL_FORMAT_RGBA_5551:
case GGL_PIXEL_FORMAT_RGBA_4444:
format = internalformat;
- break;
+ break;
case GGL_PIXEL_FORMAT_RGBX_8888:
case GGL_PIXEL_FORMAT_RGB_888:
case GGL_PIXEL_FORMAT_RGB_565:
@@ -1215,7 +1300,7 @@ void glCopyTexImage2D(
case GL_LUMINANCE:
case GL_RGB:
format = internalformat;
- break;
+ break;
}
break;
}
@@ -1235,7 +1320,7 @@ void glCopyTexImage2D(
ogles_error(c, error);
return;
}
-
+
// The bottom row is stored first in textures
GGLSurface txSurface(*surface);
txSurface.stride = -txSurface.stride;
@@ -1245,7 +1330,7 @@ void glCopyTexImage2D(
int err = copyPixels(c,
txSurface, 0, 0,
- cbSurface, x, y, cbSurface.width, cbSurface.height);
+ cbSurface, x, y, cbSurface.width, cbSurface.height);
if (err) {
ogles_error(c, err);
}
@@ -1295,7 +1380,7 @@ void glCopyTexSubImage2D(
int err = copyPixels(c,
surface, xoffset, yoffset,
- cbSurface, x, y, width, height);
+ cbSurface, x, y, width, height);
if (err) {
ogles_error(c, err);
return;
@@ -1365,7 +1450,7 @@ void glReadPixels(
return;
}
- ggl->colorBuffer(ggl, &userSurface); // destination is user buffer
+ 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);
@@ -1419,3 +1504,56 @@ 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) {
+ ogles_error(c, GL_INVALID_ENUM);
+ return;
+ }
+
+ android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
+ ogles_error(c, GL_INVALID_VALUE);
+ return;
+ }
+ if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
+ ogles_error(c, GL_INVALID_VALUE);
+ return;
+ }
+
+ // bind it to the texture unit
+ sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
+ tex->setImage(native_buffer);
+
+ /*
+ * Here an implementation can retrieve the buffer_handle_t of this buffer
+ * which gives it access to an arbitrary-defined kernel resource
+ * (or anything else for that matter).
+ * There needs to be an intimate knowledge between GLES and buffer_handle_t,
+ * so make sure to validate the handle before using it.
+ * Typically, buffer_handle_t comes from the gralloc HAL which is provided
+ * by the implementor of GLES.
+ *
+ */
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+ tex->copybits_fd = -1;
+ private_handle_t* hand;
+ if ((hand = private_handle_t::dynamicCast(native_buffer->handle)) != NULL) {
+ if (hand->usesPhysicallyContiguousMemory()) {
+ tex->copybits_fd = hand->fd;
+ }
+ }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+}
+
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+}
diff --git a/opengl/libagl/texture.h b/opengl/libagl/texture.h
index 5c57948..98f7550 100644
--- a/opengl/libagl/texture.h
+++ b/opengl/libagl/texture.h
@@ -32,13 +32,9 @@ namespace android {
void ogles_init_texture(ogles_context_t* c);
void ogles_uninit_texture(ogles_context_t* c);
-void ogles_validate_texture_impl(ogles_context_t* c);
-
-inline void ogles_validate_texture(ogles_context_t* c) {
- if (c->rasterizer.state.enables & GGL_ENABLE_TMUS)
- ogles_validate_texture_impl(c);
-}
-
+void ogles_validate_texture(ogles_context_t* c);
+void ogles_lock_textures(ogles_context_t* c);
+void ogles_unlock_textures(ogles_context_t* c);
}; // namespace android