Integrate from //sandbox/mathias/donut/...@145728
SurfaceFlinger rework for new EGL driver model support.
This commit is contained in:
@@ -15,6 +15,8 @@ ifneq ($(USE_CUSTOM_RUNTIME_HEAP_MAX),)
|
||||
LOCAL_CFLAGS += -DCUSTOM_RUNTIME_HEAP_MAX=$(USE_CUSTOM_RUNTIME_HEAP_MAX)
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
ActivityManager.cpp \
|
||||
AndroidRuntime.cpp \
|
||||
|
||||
@@ -235,7 +235,8 @@ static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
|
||||
|
||||
SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
|
||||
SkBitmap bitmap;
|
||||
bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, info.bpr);
|
||||
ssize_t bpr = info.s * bytesPerPixel(info.format);
|
||||
bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
|
||||
if (info.w > 0 && info.h > 0) {
|
||||
bitmap.setPixels(info.bits);
|
||||
} else {
|
||||
@@ -289,26 +290,8 @@ static void Surface_unlockCanvasAndPost(
|
||||
static void Surface_unlockCanvas(
|
||||
JNIEnv* env, jobject clazz, jobject argCanvas)
|
||||
{
|
||||
jobject canvas = env->GetObjectField(clazz, so.canvas);
|
||||
if (canvas != argCanvas) {
|
||||
doThrow(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
const sp<Surface>& surface = getSurface(env, clazz);
|
||||
if (!surface->isValid())
|
||||
return;
|
||||
|
||||
status_t err = surface->unlock();
|
||||
if (err < 0) {
|
||||
doThrow(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
|
||||
int saveCount = env->GetIntField(clazz, so.saveCount);
|
||||
nativeCanvas->restoreToCount(saveCount);
|
||||
nativeCanvas->setBitmapDevice(SkBitmap());
|
||||
env->SetIntField(clazz, so.saveCount, 0);
|
||||
// XXX: this API has been removed
|
||||
doThrow(env, "java/lang/IllegalArgumentException", NULL);
|
||||
}
|
||||
|
||||
static void Surface_openTransaction(
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
#include <ui/Surface.h>
|
||||
#include <SkBitmap.h>
|
||||
#include <SkPixelRef.h>
|
||||
@@ -338,7 +337,7 @@ not_valid_surface:
|
||||
goto not_valid_surface;
|
||||
|
||||
jint* base = beginNativeAttribList(_env, attrib_list);
|
||||
EGLSurface sur = eglCreateWindowSurface(dpy, cnf, new EGLNativeWindowSurface(window), base);
|
||||
EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window, base);
|
||||
endNativeAttributeList(_env, attrib_list, base);
|
||||
return (jint)sur;
|
||||
}
|
||||
|
||||
0
core/res/res/drawable/stat_sys_signal_flightmode.png
Normal file → Executable file
0
core/res/res/drawable/stat_sys_signal_flightmode.png
Normal file → Executable file
|
Before Width: | Height: | Size: 898 B After Width: | Height: | Size: 898 B |
@@ -26,6 +26,7 @@
|
||||
#endif
|
||||
|
||||
#include <private/pixelflinger/ggl_context.h>
|
||||
#include <hardware/copybit.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
@@ -39,7 +40,7 @@ class EGLSurfaceManager;
|
||||
class EGLBufferObjectManager;
|
||||
|
||||
namespace gl {
|
||||
|
||||
|
||||
struct ogles_context_t;
|
||||
struct matrixx_t;
|
||||
struct transform_t;
|
||||
@@ -96,7 +97,7 @@ struct vec4_t {
|
||||
|
||||
struct vertex_t {
|
||||
enum {
|
||||
// these constant matter for our clipping
|
||||
// these constant matter for our clipping
|
||||
CLIP_L = 0x0001, // clipping flags
|
||||
CLIP_R = 0x0002,
|
||||
CLIP_B = 0x0004,
|
||||
@@ -106,7 +107,7 @@ struct vertex_t {
|
||||
|
||||
EYE = 0x0040,
|
||||
RESERVED = 0x0080,
|
||||
|
||||
|
||||
USER_CLIP_0 = 0x0100, // user clipping flags
|
||||
USER_CLIP_1 = 0x0200,
|
||||
USER_CLIP_2 = 0x0400,
|
||||
@@ -121,7 +122,7 @@ struct vertex_t {
|
||||
USER_CLIP_ALL = 0x3F00,
|
||||
CLIP_ALL = 0x3F3F,
|
||||
};
|
||||
|
||||
|
||||
// the fields below are arranged to minimize d-cache usage
|
||||
// we group together, by cache-line, the fields most likely to be used
|
||||
|
||||
@@ -130,7 +131,7 @@ struct vertex_t {
|
||||
vec4_t eye;
|
||||
};
|
||||
vec4_t clip;
|
||||
|
||||
|
||||
uint32_t flags;
|
||||
size_t index; // cache tag, and vertex index
|
||||
GLfixed fog;
|
||||
@@ -142,7 +143,7 @@ struct vertex_t {
|
||||
vec4_t color;
|
||||
vec4_t texture[GGL_TEXTURE_UNIT_COUNT];
|
||||
uint32_t reserved1[4];
|
||||
|
||||
|
||||
inline void clear() {
|
||||
flags = index = locked = mru = 0;
|
||||
}
|
||||
@@ -199,7 +200,7 @@ struct array_machine_t {
|
||||
GLenum indicesType;
|
||||
buffer_t const* array_buffer;
|
||||
buffer_t const* element_array_buffer;
|
||||
|
||||
|
||||
void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei);
|
||||
void (*compileElement)(ogles_context_t*, vertex_t*, GLint);
|
||||
|
||||
@@ -410,7 +411,7 @@ struct transform_t {
|
||||
matrixx_t matrix;
|
||||
uint32_t flags;
|
||||
uint32_t ops;
|
||||
|
||||
|
||||
union {
|
||||
struct {
|
||||
void (*point2)(transform_t const* t, vec4_t*, vec4_t const*);
|
||||
@@ -509,17 +510,17 @@ struct viewport_t {
|
||||
GLint x;
|
||||
GLint y;
|
||||
GLsizei w;
|
||||
GLsizei h;
|
||||
GLsizei h;
|
||||
struct {
|
||||
GLint x;
|
||||
GLint y;
|
||||
} surfaceport;
|
||||
} surfaceport;
|
||||
struct {
|
||||
GLint x;
|
||||
GLint y;
|
||||
GLsizei w;
|
||||
GLsizei h;
|
||||
} scissor;
|
||||
GLsizei h;
|
||||
} scissor;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -594,6 +595,16 @@ struct prims_t {
|
||||
void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*);
|
||||
};
|
||||
|
||||
struct copybits_context_t {
|
||||
// A handle to the blit engine, if it exists, else NULL.
|
||||
copybit_device_t* blitEngine;
|
||||
int32_t minScale;
|
||||
int32_t maxScale;
|
||||
// File descriptor of current drawing surface, if it's suitable for use as
|
||||
// a copybits destination, else -1.
|
||||
int drawSurfaceFd;
|
||||
};
|
||||
|
||||
struct ogles_context_t {
|
||||
context_t rasterizer;
|
||||
array_machine_t arrays __attribute__((aligned(32)));
|
||||
@@ -617,6 +628,14 @@ struct ogles_context_t {
|
||||
uint32_t transformTextures : 1;
|
||||
EGLSurfaceManager* surfaceManager;
|
||||
EGLBufferObjectManager* bufferObjectManager;
|
||||
|
||||
// copybits is only used if LIBAGL_USE_GRALLOC_COPYBITS is
|
||||
// defined, but it is always present because ogles_context_t is a public
|
||||
// struct that is used by clients of libagl. We want the size and offsets
|
||||
// to stay the same, whether or not LIBAGL_USE_GRALLOC_COPYBITS is defined.
|
||||
|
||||
copybits_context_t copybits;
|
||||
|
||||
GLenum error;
|
||||
|
||||
static inline ogles_context_t* get() {
|
||||
|
||||
@@ -32,16 +32,12 @@ namespace android {
|
||||
|
||||
struct surface_info_t { // 4 longs, 16 bytes
|
||||
enum {
|
||||
eBufferDirty = 0x01
|
||||
eBufferDirty = 0x01,
|
||||
eNeedNewBuffer = 0x02
|
||||
};
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
uint16_t stride;
|
||||
uint16_t bpr;
|
||||
uint16_t reserved;
|
||||
uint8_t format;
|
||||
uint8_t reserved[11];
|
||||
uint8_t flags;
|
||||
ssize_t bits_offset;
|
||||
status_t status;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -110,8 +106,6 @@ struct per_client_cblk_t // 4KB max
|
||||
INSPECT = 0x00000002
|
||||
};
|
||||
|
||||
per_client_cblk_t();
|
||||
|
||||
// these functions are used by the clients
|
||||
status_t validate(size_t i) const;
|
||||
int32_t lock_layer(size_t i, uint32_t flags);
|
||||
@@ -138,12 +132,9 @@ struct display_cblk_t
|
||||
|
||||
struct surface_flinger_cblk_t // 4KB max
|
||||
{
|
||||
surface_flinger_cblk_t();
|
||||
|
||||
uint8_t connected;
|
||||
uint8_t reserved[3];
|
||||
uint32_t pad[7];
|
||||
|
||||
display_cblk_t displays[NUM_DISPLAY_MAX];
|
||||
};
|
||||
|
||||
|
||||
57
include/ui/BufferMapper.h
Normal file
57
include/ui/BufferMapper.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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_UI_BUFFER_MAPPER_H
|
||||
#define ANDROID_UI_BUFFER_MAPPER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Singleton.h>
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
|
||||
struct gralloc_module_t;
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Rect;
|
||||
|
||||
class BufferMapper : public Singleton<BufferMapper>
|
||||
{
|
||||
public:
|
||||
static inline BufferMapper& get() { return getInstance(); }
|
||||
status_t map(buffer_handle_t handle, void** addr);
|
||||
status_t unmap(buffer_handle_t handle);
|
||||
status_t lock(buffer_handle_t handle, int usage, const Rect& bounds);
|
||||
status_t unlock(buffer_handle_t handle);
|
||||
|
||||
private:
|
||||
friend class Singleton<BufferMapper>;
|
||||
BufferMapper();
|
||||
mutable Mutex mLock;
|
||||
gralloc_module_t const *mAllocMod;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_UI_BUFFER_MAPPER_H
|
||||
|
||||
@@ -19,8 +19,17 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <ui/EGLNativeSurface.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
#include <utils/threads.h>
|
||||
#include <ui/Rect.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
|
||||
extern "C" EGLNativeWindowType android_createDisplaySurface(void);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
@@ -28,27 +37,84 @@ namespace android {
|
||||
|
||||
class Surface;
|
||||
|
||||
class EGLNativeWindowSurface : public EGLNativeSurface<EGLNativeWindowSurface>
|
||||
|
||||
class NativeBuffer
|
||||
: public EGLNativeBase<
|
||||
android_native_buffer_t,
|
||||
NativeBuffer,
|
||||
LightRefBase<NativeBuffer> >
|
||||
{
|
||||
public:
|
||||
EGLNativeWindowSurface(const sp<Surface>& surface);
|
||||
~EGLNativeWindowSurface();
|
||||
NativeBuffer(int w, int h, int f, int u) : BASE() {
|
||||
android_native_buffer_t::width = w;
|
||||
android_native_buffer_t::height = h;
|
||||
android_native_buffer_t::format = f;
|
||||
android_native_buffer_t::usage = u;
|
||||
android_native_buffer_t::getHandle = getHandle;
|
||||
}
|
||||
public:
|
||||
buffer_handle_t handle;
|
||||
private:
|
||||
friend class LightRefBase<NativeBuffer>;
|
||||
~NativeBuffer() { }; // this class cannot be overloaded
|
||||
static int getHandle(android_native_buffer_t const * base, buffer_handle_t* handle) {
|
||||
*handle = getSelf(base)->handle;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
void setSwapRectangle(int l, int t, int w, int h);
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class FramebufferNativeWindow
|
||||
: public EGLNativeBase<
|
||||
android_native_window_t,
|
||||
FramebufferNativeWindow,
|
||||
LightRefBase<FramebufferNativeWindow> >
|
||||
{
|
||||
public:
|
||||
FramebufferNativeWindow();
|
||||
|
||||
framebuffer_device_t const * getDevice() const { return fbDev; }
|
||||
|
||||
private:
|
||||
static void hook_incRef(NativeWindowType window);
|
||||
static void hook_decRef(NativeWindowType window);
|
||||
static uint32_t hook_swapBuffers(NativeWindowType window);
|
||||
static void hook_connect(NativeWindowType window);
|
||||
static void hook_disconnect(NativeWindowType window);
|
||||
friend class LightRefBase<FramebufferNativeWindow>;
|
||||
~FramebufferNativeWindow(); // this class cannot be overloaded
|
||||
static void connect(android_native_window_t* window);
|
||||
static void disconnect(android_native_window_t* window);
|
||||
static int setSwapInterval(android_native_window_t* window, int interval);
|
||||
static int setSwapRectangle(android_native_window_t* window,
|
||||
int l, int t, int w, int h);
|
||||
static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
|
||||
static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
|
||||
static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
|
||||
|
||||
|
||||
uint32_t swapBuffers();
|
||||
void connect();
|
||||
void disconnect();
|
||||
|
||||
sp<Surface> mSurface;
|
||||
bool mConnected;
|
||||
static inline FramebufferNativeWindow* getSelf(
|
||||
android_native_window_t* window) {
|
||||
FramebufferNativeWindow* self =
|
||||
static_cast<FramebufferNativeWindow*>(window);
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline FramebufferNativeWindow* getSelf(
|
||||
android_native_base_t* window) {
|
||||
return getSelf(reinterpret_cast<android_native_window_t*>(window));
|
||||
}
|
||||
|
||||
|
||||
framebuffer_device_t* fbDev;
|
||||
alloc_device_t* grDev;
|
||||
|
||||
sp<NativeBuffer> buffers[2];
|
||||
sp<NativeBuffer> front;
|
||||
|
||||
Rect mDirty;
|
||||
|
||||
mutable Mutex mutex;
|
||||
Condition mCondition;
|
||||
int32_t mNumBuffers;
|
||||
int32_t mNumFreeBuffers;
|
||||
int32_t mBufferHead;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -20,12 +20,15 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/IInterface.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <ui/PixelFormat.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -33,6 +36,7 @@ typedef int32_t SurfaceID;
|
||||
|
||||
class IMemoryHeap;
|
||||
class OverlayRef;
|
||||
class SurfaceBuffer;
|
||||
|
||||
class ISurface : public IInterface
|
||||
{
|
||||
@@ -42,11 +46,13 @@ protected:
|
||||
UNREGISTER_BUFFERS,
|
||||
POST_BUFFER, // one-way transaction
|
||||
CREATE_OVERLAY,
|
||||
GET_BUFFER,
|
||||
};
|
||||
|
||||
public:
|
||||
DECLARE_META_INTERFACE(Surface);
|
||||
|
||||
virtual sp<SurfaceBuffer> getBuffer() = 0;
|
||||
|
||||
class BufferHeap {
|
||||
public:
|
||||
@@ -78,9 +84,7 @@ public:
|
||||
};
|
||||
|
||||
virtual status_t registerBuffers(const BufferHeap& buffers) = 0;
|
||||
|
||||
virtual void postBuffer(ssize_t offset) = 0; // one-way
|
||||
|
||||
virtual void unregisterBuffers() = 0;
|
||||
|
||||
virtual sp<OverlayRef> createOverlay(
|
||||
|
||||
@@ -32,7 +32,6 @@ namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class DisplayInfo;
|
||||
class IGPUCallback;
|
||||
|
||||
class ISurfaceComposer : public IInterface
|
||||
{
|
||||
@@ -112,37 +111,12 @@ public:
|
||||
*/
|
||||
virtual void bootFinished() = 0;
|
||||
|
||||
/* get access to the GPU. Access is relinquished when releasing regs */
|
||||
struct gpu_info_t {
|
||||
struct gpu_region_t {
|
||||
sp<IMemory> region;
|
||||
size_t reserved;
|
||||
};
|
||||
sp<IMemory> regs;
|
||||
size_t count;
|
||||
gpu_region_t regions[2];
|
||||
};
|
||||
virtual status_t requestGPU(
|
||||
const sp<IGPUCallback>& callback,
|
||||
gpu_info_t* gpu) = 0;
|
||||
|
||||
/* take the gpu back from any apps using it. They'll get a
|
||||
* EGL_CONTEXT_LOST error */
|
||||
virtual status_t revokeGPU() = 0;
|
||||
|
||||
/* Signal surfaceflinger that there might be some work to do
|
||||
* This is an ASYNCHRONOUS call.
|
||||
*/
|
||||
virtual void signal() const = 0;
|
||||
};
|
||||
|
||||
class IGPUCallback : public IInterface
|
||||
{
|
||||
public:
|
||||
DECLARE_META_INTERFACE(GPUCallback);
|
||||
virtual void gpuLost() = 0; //one-way
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class BnSurfaceComposer : public BnInterface<ISurfaceComposer>
|
||||
@@ -159,8 +133,6 @@ public:
|
||||
SET_ORIENTATION,
|
||||
FREEZE_DISPLAY,
|
||||
UNFREEZE_DISPLAY,
|
||||
REQUEST_GPU,
|
||||
REVOKE_GPU,
|
||||
SIGNAL
|
||||
};
|
||||
|
||||
@@ -170,15 +142,6 @@ public:
|
||||
uint32_t flags = 0);
|
||||
};
|
||||
|
||||
class BnGPUCallback : public BnInterface<IGPUCallback>
|
||||
{
|
||||
public:
|
||||
virtual status_t onTransact( uint32_t code,
|
||||
const Parcel& data,
|
||||
Parcel* reply,
|
||||
uint32_t flags = 0);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -52,7 +52,6 @@ public:
|
||||
struct surface_data_t {
|
||||
int32_t token;
|
||||
int32_t identity;
|
||||
sp<IMemoryHeap> heap[2];
|
||||
status_t readFromParcel(const Parcel& parcel);
|
||||
status_t writeToParcel(Parcel* parcel) const;
|
||||
};
|
||||
|
||||
@@ -84,6 +84,13 @@ typedef int32_t PixelFormat;
|
||||
|
||||
struct PixelFormatInfo
|
||||
{
|
||||
enum {
|
||||
INDEX_ALPHA = 0,
|
||||
INDEX_RED = 1,
|
||||
INDEX_GREEN = 2,
|
||||
INDEX_BLUE = 3
|
||||
};
|
||||
|
||||
enum { // components
|
||||
ALPHA = 1,
|
||||
RGB = 2,
|
||||
@@ -95,20 +102,33 @@ struct PixelFormatInfo
|
||||
Y_CB_CR_I = 8,
|
||||
};
|
||||
|
||||
struct szinfo {
|
||||
uint8_t h;
|
||||
uint8_t l;
|
||||
};
|
||||
|
||||
inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { }
|
||||
size_t getScanlineSize(unsigned int width) const;
|
||||
size_t getSize(size_t ci) const {
|
||||
return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0;
|
||||
}
|
||||
size_t version;
|
||||
PixelFormat format;
|
||||
size_t bytesPerPixel;
|
||||
size_t bitsPerPixel;
|
||||
uint8_t h_alpha;
|
||||
uint8_t l_alpha;
|
||||
uint8_t h_red;
|
||||
uint8_t l_red;
|
||||
uint8_t h_green;
|
||||
uint8_t l_green;
|
||||
uint8_t h_blue;
|
||||
uint8_t l_blue;
|
||||
union {
|
||||
szinfo cinfo[4];
|
||||
struct {
|
||||
uint8_t h_alpha;
|
||||
uint8_t l_alpha;
|
||||
uint8_t h_red;
|
||||
uint8_t l_red;
|
||||
uint8_t h_green;
|
||||
uint8_t l_green;
|
||||
uint8_t h_blue;
|
||||
uint8_t l_blue;
|
||||
};
|
||||
};
|
||||
uint8_t components;
|
||||
uint8_t reserved0[3];
|
||||
uint32_t reserved1;
|
||||
|
||||
@@ -28,24 +28,65 @@
|
||||
#include <ui/Region.h>
|
||||
#include <ui/ISurfaceFlingerClient.h>
|
||||
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Rect;
|
||||
class SurfaceComposerClient;
|
||||
struct per_client_cblk_t;
|
||||
struct layer_cblk_t;
|
||||
|
||||
class Surface : public RefBase
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class SurfaceBuffer
|
||||
: public EGLNativeBase<
|
||||
android_native_buffer_t,
|
||||
SurfaceBuffer,
|
||||
LightRefBase<SurfaceBuffer> >
|
||||
{
|
||||
public:
|
||||
buffer_handle_t getHandle() const {
|
||||
return handle;
|
||||
}
|
||||
|
||||
protected:
|
||||
SurfaceBuffer();
|
||||
SurfaceBuffer(const Parcel& reply);
|
||||
virtual ~SurfaceBuffer();
|
||||
buffer_handle_t handle;
|
||||
bool mOwner;
|
||||
|
||||
private:
|
||||
friend class BpSurface;
|
||||
friend class BnSurface;
|
||||
friend class LightRefBase<SurfaceBuffer>;
|
||||
|
||||
SurfaceBuffer& operator = (const SurfaceBuffer& rhs);
|
||||
const SurfaceBuffer& operator = (const SurfaceBuffer& rhs) const;
|
||||
|
||||
static status_t writeToParcel(Parcel* reply,
|
||||
android_native_buffer_t const* buffer);
|
||||
|
||||
static int getHandle(android_native_buffer_t const * base,
|
||||
buffer_handle_t* handle);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Surface
|
||||
: public EGLNativeBase<android_native_window_t, Surface, RefBase>
|
||||
{
|
||||
public:
|
||||
struct SurfaceInfo {
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
uint32_t bpr;
|
||||
uint32_t s;
|
||||
uint32_t usage;
|
||||
PixelFormat format;
|
||||
void* bits;
|
||||
void* base;
|
||||
uint32_t reserved[2];
|
||||
};
|
||||
|
||||
@@ -55,15 +96,12 @@ public:
|
||||
status_t lock(SurfaceInfo* info, bool blocking = true);
|
||||
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
|
||||
status_t unlockAndPost();
|
||||
status_t unlock();
|
||||
|
||||
void* heapBase(int i) const;
|
||||
|
||||
uint32_t getFlags() const { return mFlags; }
|
||||
|
||||
// setSwapRectangle() is mainly used by EGL
|
||||
void setSwapRectangle(const Rect& r);
|
||||
const Rect& swapRectangle() const;
|
||||
status_t nextBuffer(SurfaceInfo* info);
|
||||
|
||||
sp<Surface> dup() const;
|
||||
static sp<Surface> readFromParcel(Parcel* parcel);
|
||||
@@ -95,6 +133,8 @@ private:
|
||||
friend class Test;
|
||||
const sp<ISurface>& getISurface() const { return mSurface; }
|
||||
|
||||
status_t getBufferLocked(int index);
|
||||
|
||||
// can't be copied
|
||||
Surface& operator = (Surface& rhs);
|
||||
Surface(const Surface& rhs);
|
||||
@@ -108,23 +148,39 @@ private:
|
||||
Surface(Surface const* rhs);
|
||||
|
||||
~Surface();
|
||||
|
||||
|
||||
Region dirtyRegion() const;
|
||||
void setDirtyRegion(const Region& region) const;
|
||||
|
||||
// this locks protects calls to lockSurface() / unlockSurface()
|
||||
// and is called by SurfaceComposerClient.
|
||||
Mutex& getLock() const { return mSurfaceLock; }
|
||||
|
||||
status_t validate(per_client_cblk_t const* cblk) const;
|
||||
static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty);
|
||||
|
||||
|
||||
static void connect(android_native_window_t* window);
|
||||
static void disconnect(android_native_window_t* window);
|
||||
static int setSwapInterval(android_native_window_t* window, int interval);
|
||||
static int setSwapRectangle(android_native_window_t* window,
|
||||
int l, int t, int w, int h);
|
||||
static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
|
||||
static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
|
||||
static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
|
||||
|
||||
int dequeueBuffer(android_native_buffer_t** buffer);
|
||||
int lockBuffer(android_native_buffer_t* buffer);
|
||||
int queueBuffer(android_native_buffer_t* buffer);
|
||||
|
||||
|
||||
alloc_device_t* mAllocDevice;
|
||||
sp<SurfaceComposerClient> mClient;
|
||||
sp<ISurface> mSurface;
|
||||
sp<IMemoryHeap> mHeap[2];
|
||||
sp<SurfaceBuffer> mBuffers[2];
|
||||
android_native_buffer_t* mLockedBuffer;
|
||||
SurfaceID mToken;
|
||||
uint32_t mIdentity;
|
||||
PixelFormat mFormat;
|
||||
uint32_t mFlags;
|
||||
const bool mOwner;
|
||||
mutable void* mSurfaceHeapBase[2];
|
||||
mutable Region mDirtyRegion;
|
||||
mutable Rect mSwapRectangle;
|
||||
mutable uint8_t mBackbufferIndex;
|
||||
|
||||
@@ -128,34 +128,17 @@ private:
|
||||
status_t setPosition(Surface* surface, int32_t x, int32_t y);
|
||||
status_t setSize(Surface* surface, uint32_t w, uint32_t h);
|
||||
|
||||
//! Unlock the surface, and specify the dirty region if any
|
||||
status_t unlockAndPostSurface(Surface* surface);
|
||||
status_t unlockSurface(Surface* surface);
|
||||
|
||||
status_t lockSurface(Surface* surface,
|
||||
Surface::SurfaceInfo* info,
|
||||
Region* dirty,
|
||||
bool blocking = true);
|
||||
|
||||
status_t nextBuffer(Surface* surface,
|
||||
Surface::SurfaceInfo* info);
|
||||
void signalServer();
|
||||
|
||||
status_t destroySurface(SurfaceID sid);
|
||||
|
||||
void _init(const sp<ISurfaceComposer>& sm,
|
||||
const sp<ISurfaceFlingerClient>& conn);
|
||||
void _signal_server();
|
||||
static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty);
|
||||
|
||||
inline layer_state_t* _get_state_l(const sp<Surface>& surface);
|
||||
layer_state_t* _lockLayerState(const sp<Surface>& surface);
|
||||
inline void _unlockLayerState();
|
||||
|
||||
status_t validateSurface(
|
||||
per_client_cblk_t const* cblk, Surface const * surface);
|
||||
|
||||
void pinHeap(const sp<IMemoryHeap>& heap);
|
||||
|
||||
mutable Mutex mLock;
|
||||
layer_state_t* mPrebuiltLayerState;
|
||||
SortedVector<layer_state_t> mStates;
|
||||
@@ -167,9 +150,6 @@ private:
|
||||
per_client_cblk_t* mControl;
|
||||
sp<IMemory> mControlMemory;
|
||||
sp<ISurfaceFlingerClient> mClient;
|
||||
sp<IMemoryHeap> mSurfaceHeap;
|
||||
uint8_t* mSurfaceHeapBase;
|
||||
void* mGL;
|
||||
SurfaceFlingerSynchro* mSignalServer;
|
||||
};
|
||||
|
||||
|
||||
@@ -80,8 +80,11 @@ public:
|
||||
status_t writeStrongBinder(const sp<IBinder>& val);
|
||||
status_t writeWeakBinder(const wp<IBinder>& val);
|
||||
|
||||
// doesn't take ownership of the native_handle
|
||||
status_t writeNativeHandle(const native_handle& handle);
|
||||
// Place a native_handle into the parcel (the native_handle's file-
|
||||
// descriptors are dup'ed, so it is safe to delete the native_handle
|
||||
// when this function returns).
|
||||
// Doesn't take ownership of the native_handle.
|
||||
status_t writeNativeHandle(const native_handle* handle);
|
||||
|
||||
// Place a file descriptor into the parcel. The given fd must remain
|
||||
// valid for the lifetime of the parcel.
|
||||
@@ -114,12 +117,11 @@ public:
|
||||
wp<IBinder> readWeakBinder() const;
|
||||
|
||||
|
||||
// if alloc is NULL, native_handle is allocated with malloc(), otherwise
|
||||
// alloc is used. If the function fails, the effects of alloc() must be
|
||||
// reverted by the caller.
|
||||
native_handle* readNativeHandle(
|
||||
native_handle* (*alloc)(void* cookie, int numFds, int ints),
|
||||
void* cookie) const;
|
||||
// Retrieve native_handle from the parcel. This returns a copy of the
|
||||
// parcel's native_handle (the caller takes ownership). The caller
|
||||
// must free the native_handle with native_handle_close() and
|
||||
// native_handle_delete().
|
||||
native_handle* readNativeHandle() const;
|
||||
|
||||
|
||||
// Retrieve a file descriptor from the parcel. This returns the raw fd
|
||||
|
||||
59
include/utils/Singleton.h
Normal file
59
include/utils/Singleton.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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_UTILS_SINGLETON_H
|
||||
#define ANDROID_UTILS_SINGLETON_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename TYPE>
|
||||
class Singleton
|
||||
{
|
||||
public:
|
||||
static TYPE& getInstance() {
|
||||
Mutex::Autolock _l(sLock);
|
||||
TYPE* instance = sInstance;
|
||||
if (instance == 0) {
|
||||
instance = new TYPE();
|
||||
sInstance = instance;
|
||||
}
|
||||
return *instance;
|
||||
}
|
||||
|
||||
protected:
|
||||
~Singleton() { };
|
||||
Singleton() { };
|
||||
|
||||
private:
|
||||
Singleton(const Singleton&);
|
||||
Singleton& operator = (const Singleton&);
|
||||
static Mutex sLock;
|
||||
static TYPE* sInstance;
|
||||
};
|
||||
|
||||
template<class TYPE> Mutex Singleton<TYPE>::sLock;
|
||||
template<class TYPE> TYPE* Singleton<TYPE>::sInstance(0);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_UTILS_SINGLETON_H
|
||||
|
||||
@@ -5,9 +5,9 @@ LOCAL_SRC_FILES:= \
|
||||
clz.cpp.arm \
|
||||
DisplayHardware/DisplayHardware.cpp \
|
||||
DisplayHardware/DisplayHardwareBase.cpp \
|
||||
GPUHardware/GPUHardware.cpp \
|
||||
BootAnimation.cpp \
|
||||
BlurFilter.cpp.arm \
|
||||
BufferAllocator.cpp \
|
||||
CPUGauge.cpp \
|
||||
Layer.cpp \
|
||||
LayerBase.cpp \
|
||||
@@ -20,9 +20,10 @@ LOCAL_SRC_FILES:= \
|
||||
OrientationAnimation.cpp \
|
||||
SurfaceFlinger.cpp \
|
||||
Tokenizer.cpp \
|
||||
Transform.cpp \
|
||||
VRamHeap.cpp
|
||||
Transform.cpp
|
||||
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
|
||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
|
||||
|
||||
# need "-lrt" on Linux simulator to pick up clock_gettime
|
||||
ifeq ($(TARGET_SIMULATOR),true)
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BootAnimation"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <math.h>
|
||||
@@ -147,9 +145,7 @@ status_t BootAnimation::readyToRun() {
|
||||
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
|
||||
|
||||
mNativeWindowSurface = new EGLNativeWindowSurface(s);
|
||||
surface = eglCreateWindowSurface(display, config,
|
||||
mNativeWindowSurface.get(), NULL);
|
||||
surface = eglCreateWindowSurface(display, config, s.get(), NULL);
|
||||
|
||||
context = eglCreateContext(display, config, NULL, NULL);
|
||||
eglQuerySurface(display, surface, EGL_WIDTH, &w);
|
||||
@@ -180,7 +176,7 @@ bool BootAnimation::threadLoop() {
|
||||
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(mDisplay, mContext);
|
||||
eglDestroySurface(mDisplay, mSurface);
|
||||
mNativeWindowSurface.clear();
|
||||
mFlingerSurface.clear();
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -199,8 +195,7 @@ bool BootAnimation::android() {
|
||||
const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
|
||||
|
||||
// draw and update only what we need
|
||||
mNativeWindowSurface->setSwapRectangle(updateRect.left,
|
||||
updateRect.top, updateRect.width(), updateRect.height());
|
||||
mFlingerSurface->setSwapRectangle(updateRect);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
|
||||
|
||||
@@ -72,7 +72,6 @@ private:
|
||||
EGLDisplay mContext;
|
||||
EGLDisplay mSurface;
|
||||
sp<Surface> mFlingerSurface;
|
||||
sp<EGLNativeWindowSurface> mNativeWindowSurface;
|
||||
Barrier mBarrier;
|
||||
};
|
||||
|
||||
|
||||
162
libs/surfaceflinger/BufferAllocator.cpp
Normal file
162
libs/surfaceflinger/BufferAllocator.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
**
|
||||
** 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 <sys/mman.h>
|
||||
#include <utils/CallStack.h>
|
||||
#include <cutils/ashmem.h>
|
||||
#include <cutils/log.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include <ui/BufferMapper.h>
|
||||
|
||||
#include "BufferAllocator.h"
|
||||
|
||||
// FIXME: ANDROID_GRALLOC_DEBUG must only be used with *our* gralloc
|
||||
#define ANDROID_GRALLOC_DEBUG 1
|
||||
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Mutex BufferAllocator::sLock;
|
||||
KeyedVector<buffer_handle_t, BufferAllocator::alloc_rec_t> BufferAllocator::sAllocList;
|
||||
|
||||
BufferAllocator::BufferAllocator()
|
||||
: mAllocDev(0)
|
||||
{
|
||||
hw_module_t const* module;
|
||||
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
|
||||
LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
|
||||
if (err == 0) {
|
||||
gralloc_open(module, &mAllocDev);
|
||||
}
|
||||
}
|
||||
|
||||
BufferAllocator::~BufferAllocator()
|
||||
{
|
||||
gralloc_close(mAllocDev);
|
||||
}
|
||||
|
||||
void BufferAllocator::dump(String8& result) const
|
||||
{
|
||||
Mutex::Autolock _l(sLock);
|
||||
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
|
||||
size_t total = 0;
|
||||
const size_t SIZE = 512;
|
||||
char buffer[SIZE];
|
||||
snprintf(buffer, SIZE, "Allocated buffers:\n");
|
||||
result.append(buffer);
|
||||
const size_t c = list.size();
|
||||
for (size_t i=0 ; i<c ; i++) {
|
||||
const alloc_rec_t& rec(list.valueAt(i));
|
||||
snprintf(buffer, SIZE, "%10p: %10p | %7.2f KB | %4u x %4u | %2d | 0x%08x\n",
|
||||
list.keyAt(i), rec.vaddr, rec.size/1024.0f,
|
||||
rec.w, rec.h, rec.format, rec.usage);
|
||||
result.append(buffer);
|
||||
total += rec.size;
|
||||
}
|
||||
snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f);
|
||||
result.append(buffer);
|
||||
}
|
||||
|
||||
status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
|
||||
int usage, buffer_handle_t* handle, int32_t* stride)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
|
||||
// we have a h/w allocator and h/w buffer is requested
|
||||
status_t err = mAllocDev->alloc(mAllocDev,
|
||||
w, h, format, usage, handle, stride);
|
||||
LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
|
||||
w, h, format, usage, err, strerror(-err));
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
Mutex::Autolock _l(sLock);
|
||||
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
|
||||
alloc_rec_t rec;
|
||||
rec.w = w;
|
||||
rec.h = h;
|
||||
rec.format = format;
|
||||
rec.usage = usage;
|
||||
rec.vaddr = 0;
|
||||
rec.size = h * stride[0] * bytesPerPixel(format);
|
||||
list.add(*handle, rec);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t BufferAllocator::free(buffer_handle_t handle)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
|
||||
#if ANDROID_GRALLOC_DEBUG
|
||||
if (handle->data[2]) {
|
||||
CallStack s;
|
||||
s.update();
|
||||
s.dump("");
|
||||
}
|
||||
#endif
|
||||
|
||||
status_t err = mAllocDev->free(mAllocDev, handle);
|
||||
LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
Mutex::Autolock _l(sLock);
|
||||
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
|
||||
list.removeItem(handle);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t BufferAllocator::map(buffer_handle_t handle, void** addr)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
status_t err = BufferMapper::get().map(handle, addr);
|
||||
if (err == NO_ERROR) {
|
||||
Mutex::Autolock _l(sLock);
|
||||
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
|
||||
ssize_t idx = list.indexOfKey(handle);
|
||||
if (idx >= 0)
|
||||
list.editValueAt(idx).vaddr = addr;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t BufferAllocator::unmap(buffer_handle_t handle)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
gralloc_module_t* mod = (gralloc_module_t*)mAllocDev->common.module;
|
||||
status_t err = mod->unmap(mod, handle);
|
||||
LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err));
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
Mutex::Autolock _l(sLock);
|
||||
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
|
||||
ssize_t idx = list.indexOfKey(handle);
|
||||
if (idx >= 0)
|
||||
list.editValueAt(idx).vaddr = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
100
libs/surfaceflinger/BufferAllocator.h
Normal file
100
libs/surfaceflinger/BufferAllocator.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
**
|
||||
** 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_BUFFER_ALLOCATOR_H
|
||||
#define ANDROID_BUFFER_ALLOCATOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cutils/native_handle.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Singleton.h>
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class String8;
|
||||
|
||||
class BufferAllocator : public Singleton<BufferAllocator>
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
USAGE_SW_READ_NEVER = GRALLOC_USAGE_SW_READ_NEVER,
|
||||
USAGE_SW_READ_RARELY = GRALLOC_USAGE_SW_READ_RARELY,
|
||||
USAGE_SW_READ_OFTEN = GRALLOC_USAGE_SW_READ_OFTEN,
|
||||
USAGE_SW_READ_MASK = GRALLOC_USAGE_SW_READ_MASK,
|
||||
|
||||
USAGE_SW_WRITE_NEVER = GRALLOC_USAGE_SW_WRITE_NEVER,
|
||||
USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY,
|
||||
USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN,
|
||||
USAGE_SW_WRITE_MASK = GRALLOC_USAGE_SW_WRITE_MASK,
|
||||
|
||||
USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,
|
||||
|
||||
USAGE_HW_TEXTURE = GRALLOC_USAGE_HW_TEXTURE,
|
||||
USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER,
|
||||
USAGE_HW_2D = GRALLOC_USAGE_HW_2D,
|
||||
USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK
|
||||
};
|
||||
|
||||
static inline BufferAllocator& get() { return getInstance(); }
|
||||
|
||||
|
||||
status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage,
|
||||
buffer_handle_t* handle, int32_t* stride);
|
||||
|
||||
status_t free(buffer_handle_t handle);
|
||||
|
||||
status_t map(buffer_handle_t handle, void** addr);
|
||||
|
||||
status_t unmap(buffer_handle_t handle);
|
||||
|
||||
void dump(String8& res) const;
|
||||
|
||||
private:
|
||||
struct alloc_rec_t {
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
PixelFormat format;
|
||||
uint32_t usage;
|
||||
void* vaddr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static Mutex sLock;
|
||||
static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;
|
||||
|
||||
friend class Singleton<BufferAllocator>;
|
||||
BufferAllocator();
|
||||
~BufferAllocator();
|
||||
|
||||
mutable Mutex mLock;
|
||||
alloc_device_t *mAllocDev;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_BUFFER_ALLOCATOR_H
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "CPUGauge"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
@@ -113,7 +111,7 @@ bool CPUGauge::threadLoop()
|
||||
fb.version = sizeof(GGLSurface);
|
||||
fb.width = info.w;
|
||||
fb.height = info.h;
|
||||
fb.stride = info.w;
|
||||
fb.stride = info.s;
|
||||
fb.format = info.format;
|
||||
fb.data = (GGLubyte*)info.bits;
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -23,18 +21,24 @@
|
||||
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <ui/EGLDisplaySurface.h>
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
|
||||
#include <hardware/copybit.h>
|
||||
#include <hardware/overlay.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
@@ -108,17 +112,28 @@ PixelFormat DisplayHardware::getFormat() const { return mFormat; }
|
||||
|
||||
void DisplayHardware::init(uint32_t dpy)
|
||||
{
|
||||
hw_module_t const* module;
|
||||
|
||||
mNativeWindow = new FramebufferNativeWindow();
|
||||
|
||||
mOverlayEngine = NULL;
|
||||
if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
|
||||
overlay_control_open(module, &mOverlayEngine);
|
||||
}
|
||||
|
||||
framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
|
||||
|
||||
PixelFormatInfo fbFormatInfo;
|
||||
getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo);
|
||||
|
||||
// initialize EGL
|
||||
const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 5,
|
||||
EGL_GREEN_SIZE, 6,
|
||||
EGL_BLUE_SIZE, 5,
|
||||
EGL_BUFFER_SIZE, fbFormatInfo.bitsPerPixel,
|
||||
EGL_DEPTH_SIZE, 0,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint w, h, dummy;
|
||||
EGLint numConfigs, n;
|
||||
EGLConfig config;
|
||||
EGLint numConfigs=0, n=0;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
mFlags = 0;
|
||||
@@ -129,7 +144,31 @@ void DisplayHardware::init(uint32_t dpy)
|
||||
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
eglInitialize(display, NULL, NULL);
|
||||
eglGetConfigs(display, NULL, 0, &numConfigs);
|
||||
eglChooseConfig(display, attribs, &config, 1, &n);
|
||||
|
||||
// Get all the "potential match" configs...
|
||||
EGLConfig* const configs = new EGLConfig[numConfigs];
|
||||
eglChooseConfig(display, attribs, configs, numConfigs, &n);
|
||||
LOGE_IF(n<=0, "no EGLConfig available!");
|
||||
EGLConfig config = configs[0];
|
||||
if (n > 1) {
|
||||
// if there is more than one candidate, go through the list
|
||||
// and pick one that matches our framebuffer format
|
||||
int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA);
|
||||
int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED);
|
||||
int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN);
|
||||
int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE);
|
||||
for (int i=0 ; i<n ; i++) {
|
||||
EGLint r,g,b,a;
|
||||
eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &r);
|
||||
eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g);
|
||||
eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &b);
|
||||
eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a);
|
||||
if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB == b) {
|
||||
config = configs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
delete [] configs;
|
||||
|
||||
/*
|
||||
* Gather EGL extensions
|
||||
@@ -145,11 +184,8 @@ void DisplayHardware::init(uint32_t dpy)
|
||||
LOGI("extensions: %s", egl_extensions);
|
||||
LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
|
||||
|
||||
// TODO: get this from the devfb driver (probably should be HAL module)
|
||||
mFlags |= SWAP_RECTANGLE_EXTENSION;
|
||||
|
||||
// TODO: get the real "update_on_demand" behavior (probably should be HAL module)
|
||||
mFlags |= UPDATE_ON_DEMAND;
|
||||
// FIXME: mFlags |= UPDATE_ON_DEMAND;
|
||||
|
||||
if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
|
||||
if (dummy == EGL_SLOW_CONFIG)
|
||||
@@ -160,33 +196,20 @@ void DisplayHardware::init(uint32_t dpy)
|
||||
* Create our main surface
|
||||
*/
|
||||
|
||||
mDisplaySurface = new EGLDisplaySurface();
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
|
||||
//checkEGLErrors("eglCreateDisplaySurfaceANDROID");
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
|
||||
checkEGLErrors("eglCreateDisplaySurfaceANDROID");
|
||||
|
||||
|
||||
if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
|
||||
if (dummy == EGL_BUFFER_PRESERVED) {
|
||||
mFlags |= BUFFER_PRESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
GLint value = EGL_UNKNOWN;
|
||||
eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value);
|
||||
if (value == EGL_UNKNOWN) {
|
||||
mDpiX = 160.0f;
|
||||
} else {
|
||||
mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING;
|
||||
}
|
||||
value = EGL_UNKNOWN;
|
||||
eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value);
|
||||
if (value == EGL_UNKNOWN) {
|
||||
mDpiY = 160.0f;
|
||||
} else {
|
||||
mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
|
||||
}
|
||||
mRefreshRate = 60.f; // TODO: get the real refresh rate
|
||||
|
||||
mDpiX = mNativeWindow->xdpi;
|
||||
mDpiX = mNativeWindow->ydpi;
|
||||
mRefreshRate = mNativeWindow->getDevice()->fps;
|
||||
|
||||
char property[PROPERTY_VALUE_MAX];
|
||||
if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
|
||||
@@ -225,7 +248,10 @@ void DisplayHardware::init(uint32_t dpy)
|
||||
if (strstr(gl_extensions, "GL_OES_draw_texture")) {
|
||||
mFlags |= DRAW_TEXTURE_EXTENSION;
|
||||
}
|
||||
if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) {
|
||||
if (strstr( gl_extensions, "GL_OES_EGL_image") &&
|
||||
(strstr(egl_extensions, "KHR_image_base") ||
|
||||
strstr(egl_extensions, "EGL_KHR_image")) &&
|
||||
strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
|
||||
mFlags |= DIRECT_TEXTURE;
|
||||
}
|
||||
|
||||
@@ -236,19 +262,8 @@ void DisplayHardware::init(uint32_t dpy)
|
||||
mConfig = config;
|
||||
mSurface = surface;
|
||||
mContext = context;
|
||||
mFormat = GGL_PIXEL_FORMAT_RGB_565;
|
||||
|
||||
hw_module_t const* module;
|
||||
|
||||
mBlitEngine = NULL;
|
||||
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
|
||||
copybit_open(module, &mBlitEngine);
|
||||
}
|
||||
|
||||
mOverlayEngine = NULL;
|
||||
if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
|
||||
overlay_control_open(module, &mOverlayEngine);
|
||||
}
|
||||
mFormat = fbDev->format;
|
||||
mPageFlipCount = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -262,7 +277,6 @@ void DisplayHardware::fini()
|
||||
{
|
||||
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglTerminate(mDisplay);
|
||||
copybit_close(mBlitEngine);
|
||||
overlay_control_close(mOverlayEngine);
|
||||
}
|
||||
|
||||
@@ -276,28 +290,8 @@ void DisplayHardware::acquireScreen() const
|
||||
DisplayHardwareBase::acquireScreen();
|
||||
}
|
||||
|
||||
void DisplayHardware::getDisplaySurface(copybit_image_t* img) const
|
||||
{
|
||||
img->w = mDisplaySurface->stride;
|
||||
img->h = mDisplaySurface->height;
|
||||
img->format = mDisplaySurface->format;
|
||||
img->offset = mDisplaySurface->offset;
|
||||
img->base = (void*)mDisplaySurface->base;
|
||||
img->fd = mDisplaySurface->fd;
|
||||
}
|
||||
|
||||
void DisplayHardware::getDisplaySurface(GGLSurface* fb) const
|
||||
{
|
||||
fb->version= sizeof(GGLSurface);
|
||||
fb->width = mDisplaySurface->width;
|
||||
fb->height = mDisplaySurface->height;
|
||||
fb->stride = mDisplaySurface->stride;
|
||||
fb->format = mDisplaySurface->format;
|
||||
fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset;
|
||||
}
|
||||
|
||||
uint32_t DisplayHardware::getPageFlipCount() const {
|
||||
return mDisplaySurface->getPageFlipCount();
|
||||
return mPageFlipCount;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -315,17 +309,14 @@ void DisplayHardware::flip(const Region& dirty) const
|
||||
newDirty.andSelf(Rect(mWidth, mHeight));
|
||||
|
||||
if (mFlags & BUFFER_PRESERVED) {
|
||||
const Region copyback(mDirty.subtract(newDirty));
|
||||
mDirty = newDirty;
|
||||
mDisplaySurface->copyFrontToBack(copyback);
|
||||
}
|
||||
|
||||
if (mFlags & SWAP_RECTANGLE_EXTENSION) {
|
||||
const Rect& b(newDirty.bounds());
|
||||
mDisplaySurface->setSwapRectangle(
|
||||
b.left, b.top, b.width(), b.height());
|
||||
}
|
||||
const Rect& b(newDirty.bounds());
|
||||
mNativeWindow->android_native_window_t::setSwapRectangle(
|
||||
mNativeWindow.get(), b.left, b.top, b.width(), b.height());
|
||||
|
||||
mPageFlipCount++;
|
||||
eglSwapBuffers(dpy, surface);
|
||||
checkEGLErrors("eglSwapBuffers");
|
||||
|
||||
@@ -345,9 +336,9 @@ void DisplayHardware::makeCurrent() const
|
||||
}
|
||||
|
||||
void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
|
||||
mDisplaySurface->copyFrontToImage(front);
|
||||
// FIXME: we need to get rid of this
|
||||
}
|
||||
|
||||
void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
|
||||
mDisplaySurface->copyBackToImage(front);
|
||||
// FIXME: we need to get rid of this
|
||||
}
|
||||
|
||||
@@ -22,25 +22,28 @@
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/Region.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include "DisplayHardware/DisplayHardwareBase.h"
|
||||
|
||||
struct overlay_control_device_t;
|
||||
struct copybit_device_t;
|
||||
struct framebuffer_device_t;
|
||||
struct copybit_image_t;
|
||||
struct copybit_t;
|
||||
|
||||
namespace android {
|
||||
|
||||
class EGLDisplaySurface;
|
||||
class FramebufferNativeWindow;
|
||||
|
||||
class DisplayHardware : public DisplayHardwareBase
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
DIRECT_TEXTURE = 0x00000002,
|
||||
SWAP_RECTANGLE_EXTENSION= 0x00000004,
|
||||
COPY_BITS_EXTENSION = 0x00000008,
|
||||
NPOT_EXTENSION = 0x00000100,
|
||||
DRAW_TEXTURE_EXTENSION = 0x00000200,
|
||||
@@ -73,10 +76,7 @@ public:
|
||||
void makeCurrent() const;
|
||||
|
||||
uint32_t getPageFlipCount() const;
|
||||
void getDisplaySurface(copybit_image_t* img) const;
|
||||
void getDisplaySurface(GGLSurface* fb) const;
|
||||
EGLDisplay getEGLDisplay() const { return mDisplay; }
|
||||
copybit_device_t* getBlitEngine() const { return mBlitEngine; }
|
||||
overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; }
|
||||
|
||||
void copyFrontToImage(const copybit_image_t& front) const;
|
||||
@@ -103,8 +103,9 @@ private:
|
||||
PixelFormat mFormat;
|
||||
uint32_t mFlags;
|
||||
mutable Region mDirty;
|
||||
sp<EGLDisplaySurface> mDisplaySurface;
|
||||
copybit_device_t* mBlitEngine;
|
||||
mutable uint32_t mPageFlipCount;
|
||||
|
||||
sp<FramebufferNativeWindow> mNativeWindow;
|
||||
overlay_control_device_t* mOverlayEngine;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -14,26 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/native_handle.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/StopWatch.h>
|
||||
#include <utils/IMemory.h>
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/EGLDisplaySurface.h>
|
||||
#include <ui/Surface.h>
|
||||
|
||||
#include "clz.h"
|
||||
#include "Layer.h"
|
||||
#include "LayerBitmap.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "VRamHeap.h"
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
|
||||
|
||||
@@ -54,8 +53,7 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
|
||||
mSecure(false),
|
||||
mFrontBufferIndex(1),
|
||||
mNeedsBlending(true),
|
||||
mResizeTransactionDone(false),
|
||||
mTextureName(-1U), mTextureWidth(0), mTextureHeight(0)
|
||||
mResizeTransactionDone(false)
|
||||
{
|
||||
// no OpenGL operation is possible here, since we might not be
|
||||
// in the OpenGL thread.
|
||||
@@ -63,11 +61,16 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
|
||||
|
||||
Layer::~Layer()
|
||||
{
|
||||
client->free(clientIndex());
|
||||
// this should always be called from the OpenGL thread
|
||||
if (mTextureName != -1U) {
|
||||
//glDeleteTextures(1, &mTextureName);
|
||||
deletedTextures.add(mTextureName);
|
||||
for (int i=0 ; i<NUM_BUFFERS ; i++) {
|
||||
if (mTextures[i].name != -1U) {
|
||||
// FIXME: this was originally to work-around a bug in the
|
||||
// adreno driver. this should be fixed now.
|
||||
deletedTextures.add(mTextures[i].name);
|
||||
}
|
||||
if (mTextures[i].image != EGL_NO_IMAGE_KHR) {
|
||||
EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
|
||||
eglDestroyImageKHR(dpy, mTextures[i].image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +82,7 @@ void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
|
||||
lcblk->flags |= eNoCopyBack;
|
||||
}
|
||||
|
||||
sp<LayerBaseClient::Surface> Layer::getSurface() const
|
||||
sp<LayerBaseClient::Surface> Layer::createSurface() const
|
||||
{
|
||||
return mSurface;
|
||||
}
|
||||
@@ -92,25 +95,15 @@ status_t Layer::setBuffers( Client* client,
|
||||
status_t err = getPixelFormatInfo(format, &info);
|
||||
if (err) return err;
|
||||
|
||||
// TODO: if eHardware is explicitly requested, we should fail
|
||||
// on systems where we can't allocate memory that can be used with
|
||||
// DMA engines for instance.
|
||||
|
||||
// FIXME: we always ask for hardware for now (this should come from copybit)
|
||||
flags |= ISurfaceComposer::eHardware;
|
||||
uint32_t bufferFlags = 0;
|
||||
if (flags & ISurfaceComposer::eGPU)
|
||||
bufferFlags |= Buffer::GPU;
|
||||
|
||||
const uint32_t memory_flags = flags &
|
||||
(ISurfaceComposer::eGPU |
|
||||
ISurfaceComposer::eHardware |
|
||||
ISurfaceComposer::eSecure);
|
||||
|
||||
// pixel-alignment. the final alignment may be bigger because
|
||||
// we always force a 4-byte aligned bpr.
|
||||
uint32_t alignment = 1;
|
||||
if (flags & ISurfaceComposer::eSecure)
|
||||
bufferFlags |= Buffer::SECURE;
|
||||
|
||||
if (flags & ISurfaceComposer::eGPU) {
|
||||
// FIXME: this value should come from the h/w
|
||||
alignment = 8;
|
||||
|
||||
if (bufferFlags & Buffer::GPU) {
|
||||
// FIXME: this is msm7201A specific, as its GPU only supports
|
||||
// BGRA_8888.
|
||||
if (format == PIXEL_FORMAT_RGBA_8888) {
|
||||
@@ -118,45 +111,94 @@ status_t Layer::setBuffers( Client* client,
|
||||
}
|
||||
}
|
||||
|
||||
mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
|
||||
mSecure = (bufferFlags & Buffer::SECURE) ? true : false;
|
||||
mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
|
||||
sp<MemoryDealer> allocators[2];
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
allocators[i] = client->createAllocator(memory_flags);
|
||||
if (allocators[i] == 0)
|
||||
return NO_MEMORY;
|
||||
mBuffers[i].init(allocators[i]);
|
||||
int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS);
|
||||
if (err != NO_ERROR)
|
||||
err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags);
|
||||
if (err != NO_ERROR) {
|
||||
return err;
|
||||
mBuffers[i].clear(); // clear the bits for security
|
||||
mBuffers[i].getInfo(lcblk->surface + i);
|
||||
}
|
||||
}
|
||||
|
||||
mSurface = new Surface(clientIndex(),
|
||||
allocators[0]->getMemoryHeap(),
|
||||
allocators[1]->getMemoryHeap(),
|
||||
mIdentity);
|
||||
|
||||
mSurface = new SurfaceLayer(clientIndex(), this);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void Layer::reloadTexture(const Region& dirty)
|
||||
{
|
||||
if (UNLIKELY(mTextureName == -1U)) {
|
||||
// create the texture name the first time
|
||||
// can't do that in the ctor, because it runs in another thread.
|
||||
mTextureName = createTexture();
|
||||
const sp<const Buffer>& buffer(frontBuffer().getBuffer());
|
||||
if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) {
|
||||
int index = mFrontBufferIndex;
|
||||
if (LIKELY(!mTextures[index].dirty)) {
|
||||
glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
|
||||
} else {
|
||||
// we need to recreate the texture
|
||||
EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
|
||||
|
||||
// create the new texture name if needed
|
||||
if (UNLIKELY(mTextures[index].name == -1U)) {
|
||||
mTextures[index].name = createTexture();
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
|
||||
}
|
||||
|
||||
// free the previous image
|
||||
if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
|
||||
eglDestroyImageKHR(dpy, mTextures[index].image);
|
||||
mTextures[index].image = EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
// construct an EGL_NATIVE_BUFFER_ANDROID
|
||||
android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
|
||||
|
||||
// create the new EGLImageKHR
|
||||
const EGLint attrs[] = {
|
||||
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
|
||||
EGL_NONE, EGL_NONE
|
||||
};
|
||||
mTextures[index].image = eglCreateImageKHR(
|
||||
dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
|
||||
(EGLClientBuffer)clientBuf, attrs);
|
||||
|
||||
LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR,
|
||||
"eglCreateImageKHR() failed. err=0x%4x",
|
||||
eglGetError());
|
||||
|
||||
if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
|
||||
(GLeglImageOES)mTextures[index].image);
|
||||
GLint error = glGetError();
|
||||
if (UNLIKELY(error != GL_NO_ERROR)) {
|
||||
// this failed, for instance, because we don't support
|
||||
// NPOT.
|
||||
// FIXME: do something!
|
||||
mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
|
||||
} else {
|
||||
// Everything went okay!
|
||||
mTextures[index].dirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GGLSurface t;
|
||||
if (LIKELY(buffer->getBitmapSurface(&t) == NO_ERROR)) {
|
||||
if (UNLIKELY(mTextures[0].name == -1U)) {
|
||||
mTextures[0].name = createTexture();
|
||||
}
|
||||
loadTexture(dirty, mTextures[0].name, t,
|
||||
mTextures[0].width, mTextures[0].height);
|
||||
}
|
||||
}
|
||||
const GGLSurface& t(frontBuffer().surface());
|
||||
loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight);
|
||||
}
|
||||
|
||||
|
||||
void Layer::onDraw(const Region& clip) const
|
||||
{
|
||||
if (UNLIKELY(mTextureName == -1LU)) {
|
||||
//LOGW("Layer %p doesn't have a texture", this);
|
||||
const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ?
|
||||
mFrontBufferIndex : 0;
|
||||
GLuint textureName = mTextures[index].name;
|
||||
|
||||
if (UNLIKELY(textureName == -1LU)) {
|
||||
LOGW("Layer %p doesn't have a texture", this);
|
||||
// the texture has not been created yet, this Layer has
|
||||
// in fact never been drawn into. this happens frequently with
|
||||
// SurfaceView.
|
||||
@@ -164,63 +206,66 @@ void Layer::onDraw(const Region& clip) const
|
||||
return;
|
||||
}
|
||||
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
const LayerBitmap& front(frontBuffer());
|
||||
const GGLSurface& t(front.surface());
|
||||
|
||||
status_t err = NO_ERROR;
|
||||
const int can_use_copybit = canUseCopybit();
|
||||
if (can_use_copybit) {
|
||||
// StopWatch watch("copybit");
|
||||
const State& s(drawingState());
|
||||
|
||||
copybit_image_t dst;
|
||||
hw.getDisplaySurface(&dst);
|
||||
const copybit_rect_t& drect
|
||||
= reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
|
||||
|
||||
copybit_image_t src;
|
||||
front.getBitmapSurface(&src);
|
||||
copybit_rect_t srect = { 0, 0, t.width, t.height };
|
||||
|
||||
copybit_device_t* copybit = mFlinger->getBlitEngine();
|
||||
copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation());
|
||||
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
|
||||
copybit->set_parameter(copybit, COPYBIT_DITHER,
|
||||
s.flags & ISurfaceComposer::eLayerDither ?
|
||||
COPYBIT_ENABLE : COPYBIT_DISABLE);
|
||||
|
||||
region_iterator it(clip);
|
||||
err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
|
||||
}
|
||||
|
||||
if (!can_use_copybit || err) {
|
||||
drawWithOpenGL(clip, mTextureName, t);
|
||||
}
|
||||
GGLSurface t;
|
||||
sp<const Buffer> buffer(frontBuffer().getBuffer());
|
||||
buffer->getBitmapSurface(&t);
|
||||
drawWithOpenGL(clip, textureName, t);
|
||||
}
|
||||
|
||||
status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
|
||||
sp<SurfaceBuffer> Layer::peekBuffer()
|
||||
{
|
||||
LOGD_IF(DEBUG_RESIZE,
|
||||
"reallocateBuffer (layer=%p), "
|
||||
"requested (%dx%d), "
|
||||
"index=%d, (%dx%d), (%dx%d)",
|
||||
this,
|
||||
int(w), int(h),
|
||||
int(index),
|
||||
int(mBuffers[0].width()), int(mBuffers[0].height()),
|
||||
int(mBuffers[1].width()), int(mBuffers[1].height()));
|
||||
/*
|
||||
* This is called from the client's Surface::lock(), after it locked
|
||||
* the surface successfully. We're therefore guaranteed that the
|
||||
* back-buffer is not in use by ourselves.
|
||||
* Of course, we need to validate all this, which is not trivial.
|
||||
*
|
||||
* FIXME: A resize could happen at any time here. What to do about this?
|
||||
* - resize() form post()
|
||||
* - resize() from doTransaction()
|
||||
*
|
||||
* We'll probably need an internal lock for this.
|
||||
*
|
||||
*
|
||||
* TODO: We need to make sure that post() doesn't swap
|
||||
* the buffers under us.
|
||||
*/
|
||||
|
||||
status_t err = mBuffers[index].resize(w, h);
|
||||
if (err == NO_ERROR) {
|
||||
mBuffers[index].getInfo(lcblk->surface + index);
|
||||
} else {
|
||||
LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
|
||||
index, w, h, err, strerror(err));
|
||||
// XXX: what to do, what to do? We could try to free some
|
||||
// hidden surfaces, instead of killing this one?
|
||||
// it's okay to read swapState for the purpose of figuring out the
|
||||
// backbuffer index, which cannot change (since the app has locked it).
|
||||
const uint32_t state = lcblk->swapState;
|
||||
const int32_t backBufferIndex = layer_cblk_t::backBuffer(state);
|
||||
|
||||
// get rid of the EGL image, since we shouldn't need it anymore
|
||||
// (note that we're in a different thread than where it is being used)
|
||||
if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) {
|
||||
EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
|
||||
eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image);
|
||||
mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
return err;
|
||||
|
||||
LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
|
||||
sp<SurfaceBuffer> buffer = layerBitmap.allocate();
|
||||
|
||||
LOGD_IF(DEBUG_RESIZE,
|
||||
"Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
|
||||
this, backBufferIndex,
|
||||
layerBitmap.getWidth(),
|
||||
layerBitmap.getHeight(),
|
||||
layerBitmap.getBuffer()->getWidth(),
|
||||
layerBitmap.getBuffer()->getHeight());
|
||||
|
||||
if (UNLIKELY(buffer == 0)) {
|
||||
// XXX: what to do, what to do?
|
||||
} else {
|
||||
// texture is now dirty...
|
||||
mTextures[backBufferIndex].dirty = true;
|
||||
// ... so it the visible region (because we consider the surface's
|
||||
// buffer size for visibility calculations)
|
||||
forceVisibilityTransaction();
|
||||
mFlinger->setTransactionFlags(eTraversalNeeded);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint32_t Layer::doTransaction(uint32_t flags)
|
||||
@@ -232,7 +277,7 @@ uint32_t Layer::doTransaction(uint32_t flags)
|
||||
// that the size changed back to its previous value before the buffer
|
||||
// was resized (in the eLocked case below), in which case, we still
|
||||
// need to execute the code below so the clients have a chance to be
|
||||
// release. resze() deals with the fact that the size can be the same.
|
||||
// release. resize() deals with the fact that the size can be the same.
|
||||
|
||||
/*
|
||||
* Various states we could be in...
|
||||
@@ -276,8 +321,8 @@ uint32_t Layer::doTransaction(uint32_t flags)
|
||||
int(temp.w), int(temp.h),
|
||||
int(drawingState().w), int(drawingState().h),
|
||||
int(clientBackBufferIndex),
|
||||
int(mBuffers[0].width()), int(mBuffers[0].height()),
|
||||
int(mBuffers[1].width()), int(mBuffers[1].height()));
|
||||
int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
|
||||
int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
|
||||
// if we get there we're pretty screwed. the only reasonable
|
||||
// thing to do is to pretend we should do the resize since
|
||||
// backbufferChanged is set (this also will give a chance to
|
||||
@@ -299,8 +344,8 @@ uint32_t Layer::doTransaction(uint32_t flags)
|
||||
int(temp.w), int(temp.h),
|
||||
int(drawingState().w), int(drawingState().h),
|
||||
int(clientBackBufferIndex),
|
||||
int(mBuffers[0].width()), int(mBuffers[0].height()),
|
||||
int(mBuffers[1].width()), int(mBuffers[1].height()));
|
||||
int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
|
||||
int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
|
||||
|
||||
if (state & eLocked) {
|
||||
// if the buffer is locked, we can't resize anything because
|
||||
@@ -314,7 +359,8 @@ uint32_t Layer::doTransaction(uint32_t flags)
|
||||
status_t err =
|
||||
resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
|
||||
if (err == NO_ERROR) {
|
||||
const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
|
||||
const uint32_t mask = clientBackBufferIndex ?
|
||||
eResizeBuffer1 : eResizeBuffer0;
|
||||
android_atomic_and(~mask, &(lcblk->swapState));
|
||||
// since a buffer became available, we can let the client go...
|
||||
mFlinger->scheduleBroadcast(client);
|
||||
@@ -353,14 +399,15 @@ status_t Layer::resize(
|
||||
{
|
||||
/*
|
||||
* handle resize (backbuffer and frontbuffer reallocation)
|
||||
* this is called from post() or from doTransaction()
|
||||
*/
|
||||
|
||||
const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);
|
||||
|
||||
// if the new (transaction) size is != from the the backbuffer
|
||||
// then we need to reallocate the backbuffer
|
||||
bool backbufferChanged = (clientBackBuffer.width() != width) ||
|
||||
(clientBackBuffer.height() != height);
|
||||
bool backbufferChanged = (clientBackBuffer.getWidth() != width) ||
|
||||
(clientBackBuffer.getHeight() != height);
|
||||
|
||||
LOGD_IF(!backbufferChanged,
|
||||
"(%s) eResizeRequested (layer=%p), but size not changed: "
|
||||
@@ -372,18 +419,28 @@ status_t Layer::resize(
|
||||
int(currentState().w), int(currentState().h),
|
||||
long(lcblk->swapState),
|
||||
int(clientBackBufferIndex),
|
||||
int(mBuffers[0].width()), int(mBuffers[0].height()),
|
||||
int(mBuffers[1].width()), int(mBuffers[1].height()));
|
||||
int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
|
||||
int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
|
||||
|
||||
// this can happen when changing the size back and forth quickly
|
||||
status_t err = NO_ERROR;
|
||||
if (backbufferChanged) {
|
||||
err = reallocateBuffer(clientBackBufferIndex, width, height);
|
||||
}
|
||||
if (UNLIKELY(err != NO_ERROR)) {
|
||||
// couldn't reallocate the surface
|
||||
android_atomic_write(eInvalidSurface, &lcblk->swapState);
|
||||
memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t));
|
||||
|
||||
LOGD_IF(DEBUG_RESIZE,
|
||||
"resize (layer=%p), requested (%dx%d), "
|
||||
"index=%d, (%dx%d), (%dx%d)",
|
||||
this, int(width), int(height), int(clientBackBufferIndex),
|
||||
int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
|
||||
int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
|
||||
|
||||
err = mBuffers[clientBackBufferIndex].setSize(width, height);
|
||||
if (UNLIKELY(err != NO_ERROR)) {
|
||||
// This really should never happen
|
||||
LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
|
||||
clientBackBufferIndex, width, height, err, strerror(err));
|
||||
// couldn't reallocate the surface
|
||||
android_atomic_write(eInvalidSurface, &lcblk->swapState);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -457,15 +514,21 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
|
||||
|
||||
} while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
|
||||
*previousSate = oldValue;
|
||||
|
||||
|
||||
const int32_t index = (newValue & eIndex) ^ 1;
|
||||
mFrontBufferIndex = index;
|
||||
|
||||
/* NOTE: it's safe to set this flag here because this is only touched
|
||||
* from LayerBitmap::allocate(), which by construction cannot happen
|
||||
* while we're in post().
|
||||
*/
|
||||
lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty;
|
||||
|
||||
// ... post the new front-buffer
|
||||
Region dirty(lcblk->region + index);
|
||||
dirty.andSelf(frontBuffer().bounds());
|
||||
dirty.andSelf(frontBuffer().getBounds());
|
||||
|
||||
//LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
|
||||
//LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
|
||||
// oldValue, newValue, mFrontBufferIndex);
|
||||
//dirty.dump("dirty");
|
||||
|
||||
@@ -476,8 +539,8 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
|
||||
"index=%d, (%dx%d), (%dx%d)",
|
||||
this, newValue,
|
||||
int(1-index),
|
||||
int(mBuffers[0].width()), int(mBuffers[0].height()),
|
||||
int(mBuffers[1].width()), int(mBuffers[1].height()));
|
||||
int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
|
||||
int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
|
||||
|
||||
// here, we just posted the surface and we have resolved
|
||||
// the front/back buffer indices. The client is blocked, so
|
||||
@@ -522,8 +585,8 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
|
||||
|
||||
Point Layer::getPhysicalSize() const
|
||||
{
|
||||
const LayerBitmap& front(frontBuffer());
|
||||
return Point(front.width(), front.height());
|
||||
sp<const Buffer> front(frontBuffer().getBuffer());
|
||||
return Point(front->getWidth(), front->getHeight());
|
||||
}
|
||||
|
||||
void Layer::unlockPageFlip(
|
||||
@@ -561,6 +624,22 @@ void Layer::finishPageFlip()
|
||||
mFlinger->scheduleBroadcast(client);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Layer::SurfaceLayer::SurfaceLayer(SurfaceID id, const sp<Layer>& owner)
|
||||
: Surface(id, owner->getIdentity(), owner)
|
||||
{
|
||||
}
|
||||
|
||||
sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer()
|
||||
{
|
||||
sp<SurfaceBuffer> buffer = 0;
|
||||
sp<Layer> owner(getOwner());
|
||||
if (owner != 0) {
|
||||
buffer = owner->peekBuffer();
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
#include "LayerBitmap.h"
|
||||
#include "LayerBase.h"
|
||||
#include "Transform.h"
|
||||
@@ -42,6 +47,8 @@ class FreezeLock;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const int NUM_BUFFERS = 2;
|
||||
|
||||
class Layer : public LayerBaseClient
|
||||
{
|
||||
public:
|
||||
@@ -56,7 +63,7 @@ public:
|
||||
virtual ~Layer();
|
||||
|
||||
inline PixelFormat pixelFormat() const {
|
||||
return frontBuffer().pixelFormat();
|
||||
return frontBuffer().getPixelFormat();
|
||||
}
|
||||
|
||||
status_t setBuffers( Client* client,
|
||||
@@ -73,8 +80,7 @@ public:
|
||||
virtual void finishPageFlip();
|
||||
virtual bool needsBlending() const { return mNeedsBlending; }
|
||||
virtual bool isSecure() const { return mSecure; }
|
||||
virtual GLuint getTextureName() const { return mTextureName; }
|
||||
virtual sp<Surface> getSurface() const;
|
||||
virtual sp<Surface> createSurface() const;
|
||||
|
||||
const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; }
|
||||
LayerBitmap& getBuffer(int i) { return mBuffers[i]; }
|
||||
@@ -96,21 +102,43 @@ private:
|
||||
|
||||
status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what);
|
||||
Region post(uint32_t* oldState, bool& recomputeVisibleRegions);
|
||||
status_t reallocateBuffer(int32_t index, uint32_t w, uint32_t h);
|
||||
sp<SurfaceBuffer> peekBuffer();
|
||||
|
||||
|
||||
class SurfaceLayer : public LayerBaseClient::Surface
|
||||
{
|
||||
public:
|
||||
SurfaceLayer(SurfaceID id, const sp<Layer>& owner);
|
||||
|
||||
private:
|
||||
virtual sp<SurfaceBuffer> getBuffer();
|
||||
|
||||
sp<Layer> getOwner() const {
|
||||
return static_cast<Layer*>(Surface::getOwner().get());
|
||||
}
|
||||
};
|
||||
friend class SurfaceLayer;
|
||||
|
||||
struct Texture {
|
||||
Texture() : name(-1U), width(0), height(0), image(EGL_NO_IMAGE_KHR),
|
||||
dirty(true) { }
|
||||
GLuint name;
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
EGLImageKHR image;
|
||||
bool dirty;
|
||||
};
|
||||
|
||||
sp<Surface> mSurface;
|
||||
|
||||
bool mSecure;
|
||||
LayerBitmap mBuffers[2];
|
||||
LayerBitmap mBuffers[NUM_BUFFERS];
|
||||
Texture mTextures[NUM_BUFFERS];
|
||||
int32_t mFrontBufferIndex;
|
||||
bool mNeedsBlending;
|
||||
bool mResizeTransactionDone;
|
||||
Region mPostedDirtyRegion;
|
||||
sp<FreezeLock> mFreezeLock;
|
||||
|
||||
GLuint mTextureName;
|
||||
GLuint mTextureWidth;
|
||||
GLuint mTextureHeight;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/IPCThreadState.h>
|
||||
#include <utils/IServiceManager.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
@@ -62,7 +62,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
||||
mFlinger(flinger),
|
||||
mTransformed(false),
|
||||
mOrientation(0),
|
||||
mCanUseCopyBit(false),
|
||||
mTransactionFlags(0),
|
||||
mPremultipliedAlpha(true),
|
||||
mIdentity(uint32_t(android_atomic_inc(&sIdentity))),
|
||||
@@ -265,43 +264,6 @@ void LayerBase::validateVisibility(const Transform& planeTransform)
|
||||
mTransformed = transformed;
|
||||
mLeft = tr.tx();
|
||||
mTop = tr.ty();
|
||||
|
||||
// see if we can/should use 2D h/w with the new configuration
|
||||
mCanUseCopyBit = false;
|
||||
copybit_device_t* copybit = mFlinger->getBlitEngine();
|
||||
if (copybit) {
|
||||
const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG);
|
||||
const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS);
|
||||
mCanUseCopyBit = true;
|
||||
if ((mOrientation < 0) && (step > 1)) {
|
||||
// arbitrary orientations not supported
|
||||
mCanUseCopyBit = false;
|
||||
} else if ((mOrientation > 0) && (step > 90)) {
|
||||
// 90 deg rotations not supported
|
||||
mCanUseCopyBit = false;
|
||||
} else if ((tr.getType() & SkMatrix::kScale_Mask) && (scaleBits < 12)) {
|
||||
// arbitrary scaling not supported
|
||||
mCanUseCopyBit = false;
|
||||
}
|
||||
#if HONOR_PREMULTIPLIED_ALPHA
|
||||
else if (needsBlending() && mPremultipliedAlpha) {
|
||||
// pre-multiplied alpha not supported
|
||||
mCanUseCopyBit = false;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
// here, we determined we can use copybit
|
||||
if (tr.getType() & SkMatrix::kScale_Mask) {
|
||||
// and we have scaling
|
||||
if (!transparentRegionScreen.isRect()) {
|
||||
// we punt because blending is cheap (h/w) and the region is
|
||||
// complex, which may causes artifacts when copying
|
||||
// scaled content
|
||||
transparentRegionScreen.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
|
||||
@@ -565,8 +527,7 @@ void LayerBase::loadTexture(const Region& dirty,
|
||||
|
||||
/*
|
||||
* In OpenGL ES we can't specify a stride with glTexImage2D (however,
|
||||
* GL_UNPACK_ALIGNMENT is 4, which in essence allows a limited form of
|
||||
* stride).
|
||||
* GL_UNPACK_ALIGNMENT is a limited form of stride).
|
||||
* So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
|
||||
* need to do something reasonable (here creating a bigger texture).
|
||||
*
|
||||
@@ -579,9 +540,11 @@ void LayerBase::loadTexture(const Region& dirty,
|
||||
*
|
||||
* This should never be a problem with POT textures
|
||||
*/
|
||||
|
||||
tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4);
|
||||
|
||||
|
||||
int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format));
|
||||
unpack = 1 << ((unpack > 3) ? 3 : unpack);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
|
||||
|
||||
/*
|
||||
* round to POT if needed
|
||||
*/
|
||||
@@ -594,108 +557,80 @@ void LayerBase::loadTexture(const Region& dirty,
|
||||
texture_h = 1 << (31 - clz(t.height));
|
||||
if (texture_w < t.width) texture_w <<= 1;
|
||||
if (texture_h < t.height) texture_h <<= 1;
|
||||
if (texture_w != tw || texture_h != th) {
|
||||
// we can't use DIRECT_TEXTURE since we changed the size
|
||||
// of the texture
|
||||
flags &= ~DisplayHardware::DIRECT_TEXTURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DisplayHardware::DIRECT_TEXTURE) {
|
||||
// here we're guaranteed that texture_{w|h} == t{w|h}
|
||||
if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
|
||||
glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
|
||||
GL_RGB, tw, th, 0,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
|
||||
glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
|
||||
GL_RGBA, tw, th, 0,
|
||||
GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
|
||||
glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
|
||||
GL_RGBA, tw, th, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, t.data);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) {
|
||||
// TODO: add GL_BGRA extension
|
||||
} else {
|
||||
// oops, we don't handle this format, try the regular path
|
||||
goto regular;
|
||||
}
|
||||
textureWidth = tw;
|
||||
textureHeight = th;
|
||||
} else {
|
||||
|
||||
regular:
|
||||
Rect bounds(dirty.bounds());
|
||||
GLvoid* data = 0;
|
||||
if (texture_w!=textureWidth || texture_h!=textureHeight) {
|
||||
// texture size changed, we need to create a new one
|
||||
Rect bounds(dirty.bounds());
|
||||
GLvoid* data = 0;
|
||||
if (texture_w!=textureWidth || texture_h!=textureHeight) {
|
||||
// texture size changed, we need to create a new one
|
||||
|
||||
if (!textureWidth || !textureHeight) {
|
||||
// this is the first time, load the whole texture
|
||||
if (texture_w==tw && texture_h==th) {
|
||||
// we can do it one pass
|
||||
data = t.data;
|
||||
} else {
|
||||
// we have to create the texture first because it
|
||||
// doesn't match the size of the buffer
|
||||
bounds.set(Rect(tw, th));
|
||||
}
|
||||
}
|
||||
|
||||
if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_RGB, texture_w, texture_h, 0,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_RGBA, texture_w, texture_h, 0,
|
||||
GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_RGBA, texture_w, texture_h, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
} else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
|
||||
t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
|
||||
// just show the Y plane of YUV buffers
|
||||
if (!textureWidth || !textureHeight) {
|
||||
// this is the first time, load the whole texture
|
||||
if (texture_w==tw && texture_h==th) {
|
||||
// we can do it one pass
|
||||
data = t.data;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_LUMINANCE, texture_w, texture_h, 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
} else {
|
||||
// oops, we don't handle this format!
|
||||
LOGE("layer %p, texture=%d, using format %d, which is not "
|
||||
"supported by the GL", this, textureName, t.format);
|
||||
textureName = -1;
|
||||
// we have to create the texture first because it
|
||||
// doesn't match the size of the buffer
|
||||
bounds.set(Rect(tw, th));
|
||||
}
|
||||
textureWidth = texture_w;
|
||||
textureHeight = texture_h;
|
||||
}
|
||||
if (!data && textureName>=0) {
|
||||
if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
0, bounds.top, t.width, bounds.height(),
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
t.data + bounds.top*t.width*2);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
0, bounds.top, t.width, bounds.height(),
|
||||
GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
t.data + bounds.top*t.width*2);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
0, bounds.top, t.width, bounds.height(),
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
t.data + bounds.top*t.width*4);
|
||||
}
|
||||
|
||||
if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_RGB, texture_w, texture_h, 0,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_RGBA, texture_w, texture_h, 0,
|
||||
GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_RGBA, texture_w, texture_h, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
} else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
|
||||
t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
|
||||
// just show the Y plane of YUV buffers
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
GL_LUMINANCE, texture_w, texture_h, 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
} else {
|
||||
// oops, we don't handle this format!
|
||||
LOGE("layer %p, texture=%d, using format %d, which is not "
|
||||
"supported by the GL", this, textureName, t.format);
|
||||
textureName = -1;
|
||||
}
|
||||
textureWidth = texture_w;
|
||||
textureHeight = texture_h;
|
||||
}
|
||||
if (!data && textureName>=0) {
|
||||
if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
0, bounds.top, t.width, bounds.height(),
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
t.data + bounds.top*t.stride*2);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
0, bounds.top, t.width, bounds.height(),
|
||||
GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
t.data + bounds.top*t.stride*2);
|
||||
} else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
0, bounds.top, t.width, bounds.height(),
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
t.data + bounds.top*t.stride*4);
|
||||
} else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
|
||||
t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
|
||||
// just show the Y plane of YUV buffers
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
0, bounds.top, t.width, bounds.height(),
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
||||
t.data + bounds.top*t.stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LayerBase::canUseCopybit() const
|
||||
{
|
||||
return mCanUseCopyBit;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
|
||||
@@ -704,9 +639,12 @@ LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
|
||||
lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ),
|
||||
mIndex(i)
|
||||
{
|
||||
if (client) {
|
||||
client->bindLayer(this, i);
|
||||
}
|
||||
|
||||
void LayerBaseClient::onFirstRef()
|
||||
{
|
||||
if (client) {
|
||||
client->bindLayer(this, mIndex);
|
||||
// Initialize this layer's control block
|
||||
memset(this->lcblk, 0, sizeof(layer_cblk_t));
|
||||
this->lcblk->identity = mIdentity;
|
||||
@@ -729,11 +667,106 @@ int32_t LayerBaseClient::serverIndex() const {
|
||||
return 0xFFFF0000 | mIndex;
|
||||
}
|
||||
|
||||
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const
|
||||
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
|
||||
{
|
||||
return new Surface(clientIndex(), mIdentity);
|
||||
sp<Surface> s;
|
||||
Mutex::Autolock _l(mLock);
|
||||
s = mClientSurface.promote();
|
||||
if (s == 0) {
|
||||
s = createSurface();
|
||||
mClientSurface = s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
|
||||
{
|
||||
return new Surface(clientIndex(), mIdentity,
|
||||
const_cast<LayerBaseClient *>(this));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
LayerBaseClient::Surface::Surface(SurfaceID id, int identity,
|
||||
const sp<LayerBaseClient>& owner)
|
||||
: mToken(id), mIdentity(identity), mOwner(owner)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LayerBaseClient::Surface::~Surface() {
|
||||
// TODO: We now have a point here were we can clean-up the
|
||||
// client's mess.
|
||||
// This is also where surface id should be recycled.
|
||||
//LOGD("Surface %d, heaps={%p, %p} destroyed",
|
||||
// mId, mHeap[0].get(), mHeap[1].get());
|
||||
}
|
||||
|
||||
sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
|
||||
sp<LayerBaseClient> owner(mOwner.promote());
|
||||
return owner;
|
||||
}
|
||||
|
||||
|
||||
void LayerBaseClient::Surface::getSurfaceData(
|
||||
ISurfaceFlingerClient::surface_data_t* params) const
|
||||
{
|
||||
params->token = mToken;
|
||||
params->identity = mIdentity;
|
||||
}
|
||||
|
||||
status_t LayerBaseClient::Surface::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
switch (code) {
|
||||
case REGISTER_BUFFERS:
|
||||
case UNREGISTER_BUFFERS:
|
||||
case CREATE_OVERLAY:
|
||||
{
|
||||
// codes that require permission check
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
const int pid = ipc->getCallingPid();
|
||||
const int self_pid = getpid();
|
||||
if (LIKELY(pid != self_pid)) {
|
||||
// we're called from a different process, do the real check
|
||||
if (!checkCallingPermission(
|
||||
String16("android.permission.ACCESS_SURFACE_FLINGER")))
|
||||
{
|
||||
const int uid = ipc->getCallingUid();
|
||||
LOGE("Permission Denial: "
|
||||
"can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return BnSurface::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status_t LayerBaseClient::Surface::registerBuffers(
|
||||
const ISurface::BufferHeap& buffers)
|
||||
{
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
||||
void LayerBaseClient::Surface::postBuffer(ssize_t offset)
|
||||
{
|
||||
}
|
||||
|
||||
void LayerBaseClient::Surface::unregisterBuffers()
|
||||
{
|
||||
}
|
||||
|
||||
sp<OverlayRef> LayerBaseClient::Surface::createOverlay(
|
||||
uint32_t w, uint32_t h, int32_t format)
|
||||
{
|
||||
return NULL;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include <private/ui/LayerState.h>
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include <ui/Region.h>
|
||||
#include <ui/Overlay.h>
|
||||
|
||||
@@ -37,10 +39,11 @@ class SurfaceFlinger;
|
||||
class DisplayHardware;
|
||||
class GraphicPlane;
|
||||
class Client;
|
||||
class SurfaceBuffer;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class LayerBase
|
||||
class LayerBase : public RefBase
|
||||
{
|
||||
// poor man's dynamic_cast below
|
||||
template<typename T>
|
||||
@@ -72,7 +75,6 @@ public:
|
||||
static Vector<GLuint> deletedTextures;
|
||||
|
||||
LayerBase(SurfaceFlinger* flinger, DisplayID display);
|
||||
virtual ~LayerBase();
|
||||
|
||||
DisplayID dpy;
|
||||
mutable bool contentDirty;
|
||||
@@ -215,7 +217,9 @@ public:
|
||||
inline const State& currentState() const { return mCurrentState; }
|
||||
inline State& currentState() { return mCurrentState; }
|
||||
|
||||
static int compareCurrentStateZ(LayerBase*const* layerA, LayerBase*const* layerB) {
|
||||
static int compareCurrentStateZ(
|
||||
sp<LayerBase> const * layerA,
|
||||
sp<LayerBase> const * layerB) {
|
||||
return layerA[0]->currentState().z - layerB[0]->currentState().z;
|
||||
}
|
||||
|
||||
@@ -240,8 +244,6 @@ protected:
|
||||
GLint textureName, const GGLSurface& t,
|
||||
GLuint& textureWidth, GLuint& textureHeight) const;
|
||||
|
||||
bool canUseCopybit() const;
|
||||
|
||||
SurfaceFlinger* mFlinger;
|
||||
uint32_t mFlags;
|
||||
|
||||
@@ -250,7 +252,6 @@ protected:
|
||||
int32_t mOrientation;
|
||||
GLfixed mVertices[4][2];
|
||||
Rect mTransformedBounds;
|
||||
bool mCanUseCopyBit;
|
||||
int mLeft;
|
||||
int mTop;
|
||||
|
||||
@@ -269,9 +270,13 @@ protected:
|
||||
volatile int32_t mInvalidate;
|
||||
|
||||
|
||||
protected:
|
||||
virtual ~LayerBase();
|
||||
|
||||
private:
|
||||
void validateTexture(GLint textureName) const;
|
||||
static int32_t sIdentity;
|
||||
LayerBase(const LayerBase& rhs);
|
||||
void validateTexture(GLint textureName) const;
|
||||
static int32_t sIdentity;
|
||||
};
|
||||
|
||||
|
||||
@@ -289,64 +294,55 @@ public:
|
||||
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
|
||||
Client* client, int32_t i);
|
||||
virtual ~LayerBaseClient();
|
||||
|
||||
virtual void onFirstRef();
|
||||
|
||||
Client* const client;
|
||||
layer_cblk_t* const lcblk;
|
||||
|
||||
inline uint32_t getIdentity() const { return mIdentity; }
|
||||
inline int32_t clientIndex() const { return mIndex; }
|
||||
int32_t serverIndex() const;
|
||||
|
||||
virtual sp<Surface> getSurface() const;
|
||||
|
||||
uint32_t getIdentity() const { return mIdentity; }
|
||||
sp<Surface> getSurface();
|
||||
virtual sp<Surface> createSurface() const;
|
||||
|
||||
|
||||
class Surface : public BnSurface
|
||||
{
|
||||
public:
|
||||
Surface(SurfaceID id, int identity) {
|
||||
mParams.token = id;
|
||||
mParams.identity = identity;
|
||||
}
|
||||
Surface(SurfaceID id,
|
||||
const sp<IMemoryHeap>& heap0,
|
||||
const sp<IMemoryHeap>& heap1,
|
||||
int identity)
|
||||
{
|
||||
mParams.token = id;
|
||||
mParams.identity = identity;
|
||||
mParams.heap[0] = heap0;
|
||||
mParams.heap[1] = heap1;
|
||||
}
|
||||
virtual ~Surface() {
|
||||
// TODO: We now have a point here were we can clean-up the
|
||||
// client's mess.
|
||||
// This is also where surface id should be recycled.
|
||||
//LOGD("Surface %d, heaps={%p, %p} destroyed",
|
||||
// mId, mHeap[0].get(), mHeap[1].get());
|
||||
}
|
||||
|
||||
|
||||
virtual void getSurfaceData(
|
||||
ISurfaceFlingerClient::surface_data_t* params) const {
|
||||
*params = mParams;
|
||||
}
|
||||
ISurfaceFlingerClient::surface_data_t* params) const;
|
||||
|
||||
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers)
|
||||
{ return INVALID_OPERATION; }
|
||||
virtual void postBuffer(ssize_t offset) { }
|
||||
virtual void unregisterBuffers() { };
|
||||
virtual sp<OverlayRef> createOverlay(
|
||||
uint32_t w, uint32_t h, int32_t format) {
|
||||
return NULL;
|
||||
};
|
||||
protected:
|
||||
Surface(SurfaceID id, int identity, const sp<LayerBaseClient>& owner);
|
||||
virtual ~Surface();
|
||||
virtual status_t onTransact(uint32_t code, const Parcel& data,
|
||||
Parcel* reply, uint32_t flags);
|
||||
sp<LayerBaseClient> getOwner() const;
|
||||
|
||||
private:
|
||||
ISurfaceFlingerClient::surface_data_t mParams;
|
||||
virtual sp<SurfaceBuffer> getBuffer();
|
||||
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
|
||||
virtual void postBuffer(ssize_t offset);
|
||||
virtual void unregisterBuffers();
|
||||
virtual sp<OverlayRef> createOverlay(uint32_t w, uint32_t h,
|
||||
int32_t format);
|
||||
|
||||
private:
|
||||
friend class LayerBaseClient;
|
||||
int32_t mToken;
|
||||
int32_t mIdentity;
|
||||
wp<LayerBaseClient> mOwner;
|
||||
};
|
||||
|
||||
private:
|
||||
int32_t mIndex;
|
||||
friend class Surface;
|
||||
|
||||
private:
|
||||
int32_t mIndex;
|
||||
mutable Mutex mLock;
|
||||
mutable wp<Surface> mClientSurface;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -14,170 +14,204 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cutils/memory.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/MemoryDealer.h>
|
||||
#include <utils/MemoryBase.h>
|
||||
#include <utils/IMemory.h>
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/Surface.h>
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include "BufferAllocator.h"
|
||||
#include "LayerBitmap.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "VRamHeap.h"
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ===========================================================================
|
||||
// Buffer and implementation of android_native_buffer_t
|
||||
// ===========================================================================
|
||||
|
||||
Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
|
||||
: SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags),
|
||||
mVStride(0)
|
||||
{
|
||||
this->format = format;
|
||||
if (w>0 && h>0) {
|
||||
mInitCheck = initSize(w, h);
|
||||
}
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
if (handle) {
|
||||
BufferAllocator& allocator = BufferAllocator::get();
|
||||
if (usage & BufferAllocator::USAGE_SW_READ_MASK) {
|
||||
allocator.unmap(handle);
|
||||
}
|
||||
allocator.free(handle);
|
||||
}
|
||||
}
|
||||
|
||||
status_t Buffer::initCheck() const {
|
||||
return mInitCheck;
|
||||
}
|
||||
|
||||
android_native_buffer_t* Buffer::getNativeBuffer() const
|
||||
{
|
||||
return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this));
|
||||
}
|
||||
|
||||
status_t Buffer::initSize(uint32_t w, uint32_t h)
|
||||
{
|
||||
status_t err = NO_ERROR;
|
||||
|
||||
BufferAllocator& allocator = BufferAllocator::get();
|
||||
|
||||
/*
|
||||
* buffers used for software rendering, but h/w composition
|
||||
* are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
|
||||
*
|
||||
* buffers used for h/w rendering and h/w composition
|
||||
* are allocated with HW_RENDER | HW_TEXTURE
|
||||
*
|
||||
* buffers used with h/w rendering and either NPOT or no egl_image_ext
|
||||
* are allocated with SW_READ_RARELY | HW_RENDER
|
||||
*
|
||||
*/
|
||||
|
||||
if (mFlags & Buffer::SECURE) {
|
||||
// secure buffer, don't store it into the GPU
|
||||
usage = BufferAllocator::USAGE_SW_READ_OFTEN |
|
||||
BufferAllocator::USAGE_SW_WRITE_OFTEN;
|
||||
} else {
|
||||
if (mFlags & Buffer::GPU) {
|
||||
// the client wants to do GL rendering
|
||||
usage = BufferAllocator::USAGE_HW_RENDER |
|
||||
BufferAllocator::USAGE_HW_TEXTURE;
|
||||
} else {
|
||||
// software rendering-client, h/w composition
|
||||
usage = BufferAllocator::USAGE_SW_READ_OFTEN |
|
||||
BufferAllocator::USAGE_SW_WRITE_OFTEN |
|
||||
BufferAllocator::USAGE_HW_TEXTURE;
|
||||
}
|
||||
}
|
||||
|
||||
err = allocator.alloc(w, h, format, usage, &handle, &stride);
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
if (usage & BufferAllocator::USAGE_SW_READ_MASK) {
|
||||
err = allocator.map(handle, &bits);
|
||||
}
|
||||
if (err == NO_ERROR) {
|
||||
width = w;
|
||||
height = h;
|
||||
mVStride = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t Buffer::getBitmapSurface(copybit_image_t* img) const
|
||||
{
|
||||
img->w = stride ?: width;
|
||||
img->h = mVStride ?: height;
|
||||
img->format = format;
|
||||
|
||||
// FIXME: this should use a native_handle
|
||||
img->offset = 0;
|
||||
img->base = bits;
|
||||
img->fd = getHandle()->data[0];
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t Buffer::getBitmapSurface(GGLSurface* sur) const
|
||||
{
|
||||
sur->version = sizeof(GGLSurface);
|
||||
sur->width = width;
|
||||
sur->height = height;
|
||||
sur->stride = stride;
|
||||
sur->format = format;
|
||||
sur->vstride = mVStride;
|
||||
sur->data = static_cast<GGLubyte*>(bits);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// LayerBitmap
|
||||
// ===========================================================================
|
||||
|
||||
|
||||
LayerBitmap::LayerBitmap()
|
||||
: mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2)
|
||||
: mInfo(0), mWidth(0), mHeight(0)
|
||||
{
|
||||
memset(&mSurface, 0, sizeof(mSurface));
|
||||
}
|
||||
|
||||
LayerBitmap::~LayerBitmap()
|
||||
{
|
||||
mSurface.data = 0;
|
||||
}
|
||||
|
||||
status_t LayerBitmap::init(const sp<MemoryDealer>& allocator)
|
||||
status_t LayerBitmap::init(surface_info_t* info,
|
||||
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
|
||||
{
|
||||
if (mAllocator != NULL)
|
||||
if (info == NULL)
|
||||
return BAD_VALUE;
|
||||
mAllocator = allocator;
|
||||
|
||||
mFormat = format;
|
||||
mFlags = flags;
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
|
||||
mInfo = info;
|
||||
memset(info, 0, sizeof(surface_info_t));
|
||||
info->flags = surface_info_t::eNeedNewBuffer;
|
||||
|
||||
// init the buffer, but don't trigger an allocation
|
||||
mBuffer = new Buffer(0, 0, format, flags);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment,
|
||||
PixelFormat format, uint32_t flags)
|
||||
status_t LayerBitmap::setSize(uint32_t w, uint32_t h)
|
||||
{
|
||||
const sp<MemoryDealer>& allocator(mAllocator);
|
||||
if (allocator == NULL)
|
||||
return NO_INIT;
|
||||
|
||||
if (UNLIKELY(w == mSurface.width && h == mSurface.height &&
|
||||
format == mSurface.format))
|
||||
{ // same format and size, do nothing.
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
PixelFormatInfo info;
|
||||
getPixelFormatInfo(format, &info);
|
||||
|
||||
uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED;
|
||||
const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT
|
||||
const uint32_t Bpp = info.bytesPerPixel;
|
||||
uint32_t stride = (w + (alignment-1)) & ~(alignment-1);
|
||||
stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp;
|
||||
size_t size = info.getScanlineSize(stride) * h;
|
||||
if (allocFlags & MemoryDealer::PAGE_ALIGNED) {
|
||||
size_t pagesize = getpagesize();
|
||||
size = (size + (pagesize-1)) & ~(pagesize-1);
|
||||
}
|
||||
|
||||
/* FIXME: we should be able to have a h/v stride because the user of the
|
||||
* surface might have stride limitation (for instance h/w codecs often do)
|
||||
*/
|
||||
int32_t vstride = 0;
|
||||
|
||||
mAlignment = alignment;
|
||||
mAllocFlags = allocFlags;
|
||||
mOffset = 0;
|
||||
if (mSize != size) {
|
||||
// would be nice to have a reallocate() api
|
||||
mBitsMemory.clear(); // free-memory
|
||||
mBitsMemory = allocator->allocate(size, allocFlags);
|
||||
mSize = size;
|
||||
} else {
|
||||
// don't erase memory if we didn't have to reallocate
|
||||
flags &= ~SECURE_BITS;
|
||||
}
|
||||
if (mBitsMemory != 0) {
|
||||
mOffset = mBitsMemory->offset();
|
||||
mSurface.data = static_cast<GGLubyte*>(mBitsMemory->pointer());
|
||||
mSurface.version = sizeof(GGLSurface);
|
||||
mSurface.width = w;
|
||||
mSurface.height = h;
|
||||
mSurface.stride = stride;
|
||||
mSurface.vstride = vstride;
|
||||
mSurface.format = format;
|
||||
if (flags & SECURE_BITS)
|
||||
clear();
|
||||
}
|
||||
|
||||
if (mBitsMemory==0 || mSurface.data==0) {
|
||||
LOGE("not enough memory for layer bitmap size=%u", size);
|
||||
allocator->dump("LayerBitmap");
|
||||
mSurface.data = 0;
|
||||
mSize = -1U;
|
||||
return NO_MEMORY;
|
||||
Mutex::Autolock _l(mLock);
|
||||
if ((w != mWidth) || (h != mHeight)) {
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
// this will signal the client that it needs to asks us for a new buffer
|
||||
mInfo->flags = surface_info_t::eNeedNewBuffer;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void LayerBitmap::clear()
|
||||
sp<Buffer> LayerBitmap::allocate()
|
||||
{
|
||||
// NOTE: this memset should not be necessary, at least for
|
||||
// opaque surface. However, for security reasons it's better to keep it
|
||||
// (in the case of pmem, it's possible that the memory contains old
|
||||
// data)
|
||||
if (mSurface.data) {
|
||||
memset(mSurface.data, 0, mSize);
|
||||
//if (bytesPerPixel(mSurface.format) == 4) {
|
||||
// android_memset32((uint32_t*)mSurface.data, 0xFF0000FF, mSize);
|
||||
//} else {
|
||||
// android_memset16((uint16_t*)mSurface.data, 0xF800, mSize);
|
||||
//}
|
||||
Mutex::Autolock _l(mLock);
|
||||
sp<Buffer> buffer(mBuffer);
|
||||
const uint32_t w = mWidth;
|
||||
const uint32_t h = mHeight;
|
||||
if (w != buffer->getWidth() || h != buffer->getHeight()) {
|
||||
surface_info_t* info = mInfo;
|
||||
buffer = new Buffer(w, h, mFormat, mFlags);
|
||||
status_t err = buffer->initCheck();
|
||||
if (LIKELY(err == NO_ERROR)) {
|
||||
info->flags = surface_info_t::eBufferDirty;
|
||||
info->status = NO_ERROR;
|
||||
} else {
|
||||
memset(info, 0, sizeof(surface_info_t));
|
||||
info->status = NO_MEMORY;
|
||||
}
|
||||
mBuffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
status_t LayerBitmap::getInfo(surface_info_t* info) const
|
||||
{
|
||||
if (mSurface.data == 0) {
|
||||
memset(info, 0, sizeof(surface_info_t));
|
||||
info->bits_offset = NO_MEMORY;
|
||||
return NO_MEMORY;
|
||||
}
|
||||
info->w = uint16_t(width());
|
||||
info->h = uint16_t(height());
|
||||
info->stride= uint16_t(stride());
|
||||
info->bpr = uint16_t(stride() * bytesPerPixel(pixelFormat()));
|
||||
info->format= uint8_t(pixelFormat());
|
||||
info->flags = surface_info_t::eBufferDirty;
|
||||
info->bits_offset = ssize_t(mOffset);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t LayerBitmap::resize(uint32_t w, uint32_t h)
|
||||
{
|
||||
int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS);
|
||||
return err;
|
||||
}
|
||||
|
||||
size_t LayerBitmap::size() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
void LayerBitmap::getBitmapSurface(copybit_image_t* img) const
|
||||
{
|
||||
const sp<IMemoryHeap>& mh(getAllocator()->getMemoryHeap());
|
||||
void* sbase = mh->base();
|
||||
const GGLSurface& t(surface());
|
||||
img->w = t.stride ?: t.width;
|
||||
img->h = t.vstride ?: t.height;
|
||||
img->format = t.format;
|
||||
img->offset = intptr_t(t.data) - intptr_t(sbase);
|
||||
img->base = sbase;
|
||||
img->fd = mh->heapID();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -20,63 +20,117 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
#include <utils/Atomic.h>
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <private/ui/SharedState.h>
|
||||
#include <ui/Surface.h>
|
||||
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include <private/ui/SharedState.h>
|
||||
|
||||
|
||||
class copybit_image_t;
|
||||
struct android_native_buffer_t;
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class IMemory;
|
||||
class MemoryDealer;
|
||||
class LayerBitmap;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ===========================================================================
|
||||
// Buffer
|
||||
// ===========================================================================
|
||||
|
||||
class NativeBuffer;
|
||||
|
||||
class Buffer : public SurfaceBuffer
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
DONT_CLEAR = 0x00000001,
|
||||
GPU = 0x00000002,
|
||||
SECURE = 0x00000004
|
||||
};
|
||||
|
||||
// creates w * h buffer
|
||||
Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
|
||||
|
||||
// return status
|
||||
status_t initCheck() const;
|
||||
|
||||
uint32_t getWidth() const { return width; }
|
||||
uint32_t getHeight() const { return height; }
|
||||
uint32_t getStride() const { return stride; }
|
||||
uint32_t getUsage() const { return usage; }
|
||||
PixelFormat getPixelFormat() const { return format; }
|
||||
Rect getBounds() const { return Rect(width, height); }
|
||||
|
||||
status_t getBitmapSurface(copybit_image_t* img) const;
|
||||
status_t getBitmapSurface(GGLSurface* surface) const;
|
||||
|
||||
android_native_buffer_t* getNativeBuffer() const;
|
||||
|
||||
private:
|
||||
friend class LightRefBase<Buffer>;
|
||||
Buffer(const Buffer& rhs);
|
||||
~Buffer();
|
||||
Buffer& operator = (const Buffer& rhs);
|
||||
const Buffer& operator = (const Buffer& rhs) const;
|
||||
|
||||
status_t initSize(uint32_t w, uint32_t h);
|
||||
|
||||
ssize_t mInitCheck;
|
||||
uint32_t mFlags;
|
||||
uint32_t mVStride;
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// LayerBitmap
|
||||
// ===========================================================================
|
||||
|
||||
class LayerBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
// erase memory to ensure security when necessary
|
||||
SECURE_BITS = 0x00000001
|
||||
DONT_CLEAR = Buffer::DONT_CLEAR,
|
||||
GPU = Buffer::GPU,
|
||||
SECURE = Buffer::SECURE
|
||||
};
|
||||
LayerBitmap();
|
||||
~LayerBitmap();
|
||||
|
||||
LayerBitmap();
|
||||
~LayerBitmap();
|
||||
status_t init(const sp<MemoryDealer>& allocator);
|
||||
status_t init(surface_info_t* info,
|
||||
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
|
||||
|
||||
status_t setBits(uint32_t w, uint32_t h, uint32_t alignment,
|
||||
PixelFormat format, uint32_t flags = 0);
|
||||
void clear();
|
||||
status_t setSize(uint32_t w, uint32_t h);
|
||||
|
||||
status_t getInfo(surface_info_t* info) const;
|
||||
status_t resize(uint32_t w, uint32_t h);
|
||||
|
||||
const GGLSurface& surface() const { return mSurface; }
|
||||
Rect bounds() const { return Rect(width(), height()); }
|
||||
uint32_t width() const { return surface().width; }
|
||||
uint32_t height() const { return surface().height; }
|
||||
uint32_t stride() const { return surface().stride; }
|
||||
PixelFormat pixelFormat() const { return surface().format; }
|
||||
void* serverBits() const { return surface().data; }
|
||||
size_t size() const;
|
||||
const sp<MemoryDealer>& getAllocator() const { return mAllocator; }
|
||||
void getBitmapSurface(copybit_image_t* img) const;
|
||||
sp<Buffer> allocate();
|
||||
|
||||
sp<const Buffer> getBuffer() const { return mBuffer; }
|
||||
sp<Buffer> getBuffer() { return mBuffer; }
|
||||
|
||||
uint32_t getWidth() const { return mWidth; }
|
||||
uint32_t getHeight() const { return mHeight; }
|
||||
PixelFormat getPixelFormat() const { return mBuffer->getPixelFormat(); }
|
||||
Rect getBounds() const { return mBuffer->getBounds(); }
|
||||
|
||||
private:
|
||||
sp<MemoryDealer> mAllocator;
|
||||
sp<IMemory> mBitsMemory;
|
||||
uint32_t mAllocFlags;
|
||||
ssize_t mOffset;
|
||||
GGLSurface mSurface;
|
||||
size_t mSize;
|
||||
uint32_t mAlignment;
|
||||
surface_info_t* mInfo;
|
||||
sp<Buffer> mBuffer;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
PixelFormat mFormat;
|
||||
uint32_t mFlags;
|
||||
// protects setSize() and allocate()
|
||||
mutable Mutex mLock;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
@@ -25,15 +23,10 @@
|
||||
#include <utils/Log.h>
|
||||
#include <utils/StopWatch.h>
|
||||
|
||||
#include <utils/IPCThreadState.h>
|
||||
#include <utils/IServiceManager.h>
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/EGLDisplaySurface.h>
|
||||
|
||||
#include "LayerBuffer.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "VRamHeap.h"
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
|
||||
|
||||
@@ -55,30 +48,12 @@ LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
|
||||
|
||||
LayerBuffer::~LayerBuffer()
|
||||
{
|
||||
sp<SurfaceBuffer> s(getClientSurface());
|
||||
if (s != 0) {
|
||||
s->disown();
|
||||
mClientSurface.clear();
|
||||
}
|
||||
}
|
||||
|
||||
sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const
|
||||
sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mClientSurface.promote();
|
||||
}
|
||||
|
||||
sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const
|
||||
{
|
||||
sp<SurfaceBuffer> s;
|
||||
Mutex::Autolock _l(mLock);
|
||||
s = mClientSurface.promote();
|
||||
if (s == 0) {
|
||||
s = new SurfaceBuffer(clientIndex(),
|
||||
return new SurfaceBuffer(clientIndex(),
|
||||
const_cast<LayerBuffer *>(this));
|
||||
mClientSurface = s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool LayerBuffer::needsBlending() const {
|
||||
@@ -192,82 +167,49 @@ sp<LayerBuffer::Source> LayerBuffer::clearSource() {
|
||||
// LayerBuffer::SurfaceBuffer
|
||||
// ============================================================================
|
||||
|
||||
LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
|
||||
: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
|
||||
LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id,
|
||||
const sp<LayerBuffer>& owner)
|
||||
: LayerBaseClient::Surface(id, owner->getIdentity(), owner)
|
||||
{
|
||||
}
|
||||
|
||||
LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
|
||||
{
|
||||
unregisterBuffers();
|
||||
mOwner = 0;
|
||||
}
|
||||
|
||||
status_t LayerBuffer::SurfaceBuffer::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
status_t LayerBuffer::SurfaceBuffer::registerBuffers(
|
||||
const ISurface::BufferHeap& buffers)
|
||||
{
|
||||
switch (code) {
|
||||
case REGISTER_BUFFERS:
|
||||
case UNREGISTER_BUFFERS:
|
||||
case CREATE_OVERLAY:
|
||||
{
|
||||
// codes that require permission check
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
const int pid = ipc->getCallingPid();
|
||||
const int self_pid = getpid();
|
||||
if (LIKELY(pid != self_pid)) {
|
||||
// we're called from a different process, do the real check
|
||||
if (!checkCallingPermission(
|
||||
String16("android.permission.ACCESS_SURFACE_FLINGER")))
|
||||
{
|
||||
const int uid = ipc->getCallingUid();
|
||||
LOGE("Permission Denial: "
|
||||
"can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return LayerBaseClient::Surface::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
|
||||
{
|
||||
LayerBuffer* owner(getOwner());
|
||||
if (owner)
|
||||
sp<LayerBuffer> owner(getOwner());
|
||||
if (owner != 0)
|
||||
return owner->registerBuffers(buffers);
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
|
||||
{
|
||||
LayerBuffer* owner(getOwner());
|
||||
if (owner)
|
||||
sp<LayerBuffer> owner(getOwner());
|
||||
if (owner != 0)
|
||||
owner->postBuffer(offset);
|
||||
}
|
||||
|
||||
void LayerBuffer::SurfaceBuffer::unregisterBuffers()
|
||||
{
|
||||
LayerBuffer* owner(getOwner());
|
||||
if (owner)
|
||||
sp<LayerBuffer> owner(getOwner());
|
||||
if (owner != 0)
|
||||
owner->unregisterBuffers();
|
||||
}
|
||||
|
||||
sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
|
||||
uint32_t w, uint32_t h, int32_t format) {
|
||||
sp<OverlayRef> result;
|
||||
LayerBuffer* owner(getOwner());
|
||||
if (owner)
|
||||
sp<LayerBuffer> owner(getOwner());
|
||||
if (owner != 0)
|
||||
result = owner->createOverlay(w, h, format);
|
||||
return result;
|
||||
}
|
||||
|
||||
void LayerBuffer::SurfaceBuffer::disown()
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
mOwner = 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// LayerBuffer::Buffer
|
||||
// ============================================================================
|
||||
@@ -437,115 +379,27 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
|
||||
status_t err = NO_ERROR;
|
||||
NativeBuffer src(buffer->getBuffer());
|
||||
const Rect& transformedBounds = mLayer.getTransformedBounds();
|
||||
const int can_use_copybit = mLayer.canUseCopybit();
|
||||
|
||||
if (can_use_copybit) {
|
||||
const int src_width = src.crop.r - src.crop.l;
|
||||
const int src_height = src.crop.b - src.crop.t;
|
||||
int W = transformedBounds.width();
|
||||
int H = transformedBounds.height();
|
||||
if (mLayer.getOrientation() & Transform::ROT_90) {
|
||||
int t(W); W=H; H=t;
|
||||
}
|
||||
|
||||
/* With LayerBuffer, it is likely that we'll have to rescale the
|
||||
* surface, because this is often used for video playback or
|
||||
* camera-preview. Since we want these operation as fast as possible
|
||||
* we make sure we can use the 2D H/W even if it doesn't support
|
||||
* the requested scale factor, in which case we perform the scaling
|
||||
* in several passes. */
|
||||
|
||||
copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine();
|
||||
const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
|
||||
const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
|
||||
|
||||
float xscale = 1.0f;
|
||||
if (src_width > W*min) xscale = 1.0f / min;
|
||||
else if (src_width*mag < W) xscale = mag;
|
||||
|
||||
float yscale = 1.0f;
|
||||
if (src_height > H*min) yscale = 1.0f / min;
|
||||
else if (src_height*mag < H) yscale = mag;
|
||||
|
||||
if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
|
||||
if (UNLIKELY(mTemporaryDealer == 0)) {
|
||||
// allocate a memory-dealer for this the first time
|
||||
mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager()
|
||||
->createHeap(ISurfaceComposer::eHardware);
|
||||
mTempBitmap.init(mTemporaryDealer);
|
||||
}
|
||||
|
||||
const int tmp_w = floorf(src_width * xscale);
|
||||
const int tmp_h = floorf(src_height * yscale);
|
||||
err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format);
|
||||
|
||||
if (LIKELY(err == NO_ERROR)) {
|
||||
NativeBuffer tmp;
|
||||
mTempBitmap.getBitmapSurface(&tmp.img);
|
||||
tmp.crop.l = 0;
|
||||
tmp.crop.t = 0;
|
||||
tmp.crop.r = tmp.img.w;
|
||||
tmp.crop.b = tmp.img.h;
|
||||
|
||||
region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
|
||||
copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
|
||||
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
|
||||
copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
|
||||
err = copybit->stretch(copybit,
|
||||
&tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
|
||||
src = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware());
|
||||
copybit_image_t dst;
|
||||
hw.getDisplaySurface(&dst);
|
||||
const copybit_rect_t& drect
|
||||
= reinterpret_cast<const copybit_rect_t&>(transformedBounds);
|
||||
const State& s(mLayer.drawingState());
|
||||
region_iterator it(clip);
|
||||
|
||||
// pick the right orientation for this buffer
|
||||
int orientation = mLayer.getOrientation();
|
||||
if (UNLIKELY(mBufferHeap.transform)) {
|
||||
Transform rot90;
|
||||
GraphicPlane::orientationToTransfrom(
|
||||
ISurfaceComposer::eOrientation90, 0, 0, &rot90);
|
||||
const Transform& planeTransform(mLayer.graphicPlane(0).transform());
|
||||
const Layer::State& s(mLayer.drawingState());
|
||||
Transform tr(planeTransform * s.transform * rot90);
|
||||
orientation = tr.getOrientation();
|
||||
}
|
||||
|
||||
copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
|
||||
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
|
||||
copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
|
||||
|
||||
err = copybit->stretch(copybit,
|
||||
&dst, &src.img, &drect, &src.crop, &it);
|
||||
if (err != NO_ERROR) {
|
||||
LOGE("copybit failed (%s)", strerror(err));
|
||||
}
|
||||
// FIXME: We should model this after the overlay stuff
|
||||
|
||||
if (UNLIKELY(mTextureName == -1LU)) {
|
||||
mTextureName = mLayer.createTexture();
|
||||
}
|
||||
GLuint w = 0;
|
||||
GLuint h = 0;
|
||||
GGLSurface t;
|
||||
t.version = sizeof(GGLSurface);
|
||||
t.width = src.crop.r;
|
||||
t.height = src.crop.b;
|
||||
t.stride = src.img.w;
|
||||
t.vstride= src.img.h;
|
||||
t.format = src.img.format;
|
||||
t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
|
||||
const Region dirty(Rect(t.width, t.height));
|
||||
|
||||
if (!can_use_copybit || err) {
|
||||
if (UNLIKELY(mTextureName == -1LU)) {
|
||||
mTextureName = mLayer.createTexture();
|
||||
}
|
||||
GLuint w = 0;
|
||||
GLuint h = 0;
|
||||
GGLSurface t;
|
||||
t.version = sizeof(GGLSurface);
|
||||
t.width = src.crop.r;
|
||||
t.height = src.crop.b;
|
||||
t.stride = src.img.w;
|
||||
t.vstride= src.img.h;
|
||||
t.format = src.img.format;
|
||||
t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
|
||||
const Region dirty(Rect(t.width, t.height));
|
||||
mLayer.loadTexture(dirty, mTextureName, t, w, h);
|
||||
mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
|
||||
}
|
||||
// FIXME: Use EGLImage extension for this
|
||||
mLayer.loadTexture(dirty, mTextureName, t, w, h);
|
||||
mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include <utils/IMemory.h>
|
||||
#include <private/ui/LayerState.h>
|
||||
#include <EGL/eglnatives.h>
|
||||
|
||||
#include "LayerBase.h"
|
||||
#include "LayerBitmap.h"
|
||||
@@ -64,7 +63,7 @@ public:
|
||||
|
||||
virtual bool needsBlending() const;
|
||||
|
||||
virtual sp<LayerBaseClient::Surface> getSurface() const;
|
||||
virtual sp<LayerBaseClient::Surface> createSurface() const;
|
||||
virtual void onDraw(const Region& clip) const;
|
||||
virtual uint32_t doTransaction(uint32_t flags);
|
||||
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
|
||||
@@ -126,8 +125,7 @@ private:
|
||||
status_t mStatus;
|
||||
ISurface::BufferHeap mBufferHeap;
|
||||
size_t mBufferSize;
|
||||
mutable sp<MemoryDealer> mTemporaryDealer;
|
||||
mutable LayerBitmap mTempBitmap;
|
||||
mutable sp<android::Buffer> mTempBitmap;
|
||||
mutable GLuint mTextureName;
|
||||
};
|
||||
|
||||
@@ -179,23 +177,19 @@ private:
|
||||
class SurfaceBuffer : public LayerBaseClient::Surface
|
||||
{
|
||||
public:
|
||||
SurfaceBuffer(SurfaceID id, LayerBuffer* owner);
|
||||
SurfaceBuffer(SurfaceID id, const sp<LayerBuffer>& owner);
|
||||
virtual ~SurfaceBuffer();
|
||||
virtual status_t onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
|
||||
|
||||
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
|
||||
virtual void postBuffer(ssize_t offset);
|
||||
virtual void unregisterBuffers();
|
||||
|
||||
virtual sp<OverlayRef> createOverlay(
|
||||
uint32_t w, uint32_t h, int32_t format);
|
||||
void disown();
|
||||
private:
|
||||
LayerBuffer* getOwner() const {
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mOwner;
|
||||
sp<LayerBuffer> getOwner() const {
|
||||
return static_cast<LayerBuffer*>(Surface::getOwner().get());
|
||||
}
|
||||
mutable Mutex mLock;
|
||||
LayerBuffer* mOwner;
|
||||
};
|
||||
|
||||
friend class SurfaceFlinger;
|
||||
@@ -203,10 +197,8 @@ private:
|
||||
|
||||
mutable Mutex mLock;
|
||||
sp<Source> mSource;
|
||||
|
||||
bool mInvalidate;
|
||||
bool mNeedsBlending;
|
||||
mutable wp<SurfaceBuffer> mClientSurface;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
@@ -25,7 +23,6 @@
|
||||
|
||||
#include "LayerDim.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "VRamHeap.h"
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
|
||||
namespace android {
|
||||
@@ -33,8 +30,6 @@ namespace android {
|
||||
|
||||
const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10;
|
||||
const char* const LayerDim::typeID = "LayerDim";
|
||||
sp<MemoryDealer> LayerDim::mDimmerDealer;
|
||||
LayerBitmap LayerDim::mDimmerBitmap;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -46,14 +41,6 @@ LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
|
||||
|
||||
void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
|
||||
{
|
||||
// must only be called once.
|
||||
mDimmerDealer = flinger->getSurfaceHeapManager()
|
||||
->createHeap(ISurfaceComposer::eHardware);
|
||||
if (mDimmerDealer != 0) {
|
||||
mDimmerBitmap.init(mDimmerDealer);
|
||||
mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565);
|
||||
mDimmerBitmap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
LayerDim::~LayerDim()
|
||||
@@ -62,48 +49,25 @@ LayerDim::~LayerDim()
|
||||
|
||||
void LayerDim::onDraw(const Region& clip) const
|
||||
{
|
||||
// FIXME: on some h/w (like msm7K, it will be faster to use a texture)
|
||||
|
||||
const State& s(drawingState());
|
||||
|
||||
Region::iterator iterator(clip);
|
||||
if (s.alpha>0 && iterator) {
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
|
||||
status_t err = NO_ERROR;
|
||||
const int can_use_copybit = canUseCopybit();
|
||||
if (can_use_copybit) {
|
||||
// StopWatch watch("copybit");
|
||||
copybit_image_t dst;
|
||||
hw.getDisplaySurface(&dst);
|
||||
const copybit_rect_t& drect
|
||||
= reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
|
||||
|
||||
copybit_image_t src;
|
||||
mDimmerBitmap.getBitmapSurface(&src);
|
||||
const copybit_rect_t& srect(drect);
|
||||
|
||||
copybit_device_t* copybit = mFlinger->getBlitEngine();
|
||||
copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
|
||||
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
|
||||
copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
|
||||
region_iterator it(clip);
|
||||
err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
|
||||
}
|
||||
|
||||
if (!can_use_copybit || err) {
|
||||
const GGLfixed alpha = (s.alpha << 16)/255;
|
||||
const uint32_t fbHeight = hw.getHeight();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_DITHER);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4x(0, 0, 0, alpha);
|
||||
glVertexPointer(2, GL_FIXED, 0, mVertices);
|
||||
Rect r;
|
||||
while (iterator.iterate(&r)) {
|
||||
const GLint sy = fbHeight - (r.top + r.height());
|
||||
glScissor(r.left, sy, r.width(), r.height());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
const GGLfixed alpha = (s.alpha << 16)/255;
|
||||
const uint32_t fbHeight = hw.getHeight();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_DITHER);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4x(0, 0, 0, alpha);
|
||||
glVertexPointer(2, GL_FIXED, 0, mVertices);
|
||||
Rect r;
|
||||
while (iterator.iterate(&r)) {
|
||||
const GLint sy = fbHeight - (r.top + r.height());
|
||||
glScissor(r.left, sy, r.width(), r.height());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,6 @@ public:
|
||||
virtual bool isSecure() const { return false; }
|
||||
|
||||
static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h);
|
||||
|
||||
private:
|
||||
static sp<MemoryDealer> mDimmerDealer;
|
||||
static LayerBitmap mDimmerBitmap;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -24,10 +24,6 @@
|
||||
#include <utils/Log.h>
|
||||
#include <utils/StopWatch.h>
|
||||
|
||||
#include <core/SkBitmap.h>
|
||||
|
||||
#include <ui/EGLDisplaySurface.h>
|
||||
|
||||
#include "BlurFilter.h"
|
||||
#include "LayerBase.h"
|
||||
#include "LayerOrientationAnim.h"
|
||||
@@ -57,8 +53,8 @@ const float DIM_TARGET = 0.40f;
|
||||
LayerOrientationAnim::LayerOrientationAnim(
|
||||
SurfaceFlinger* flinger, DisplayID display,
|
||||
OrientationAnimation* anim,
|
||||
const LayerBitmap& bitmapIn,
|
||||
const LayerBitmap& bitmapOut)
|
||||
const sp<Buffer>& bitmapIn,
|
||||
const sp<Buffer>& bitmapOut)
|
||||
: LayerOrientationAnimBase(flinger, display), mAnim(anim),
|
||||
mBitmapIn(bitmapIn), mBitmapOut(bitmapOut),
|
||||
mTextureName(-1), mTextureNameIn(-1)
|
||||
@@ -108,11 +104,6 @@ void LayerOrientationAnim::validateVisibility(const Transform&)
|
||||
mTop = tr.ty();
|
||||
transparentRegionScreen.clear();
|
||||
mTransformed = true;
|
||||
mCanUseCopyBit = false;
|
||||
copybit_device_t* copybit = mFlinger->getBlitEngine();
|
||||
if (copybit) {
|
||||
mCanUseCopyBit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LayerOrientationAnim::onOrientationCompleted()
|
||||
@@ -135,7 +126,7 @@ void LayerOrientationAnim::onDraw(const Region& clip) const
|
||||
|
||||
// make a copy of what's on screen
|
||||
copybit_image_t image;
|
||||
mBitmapOut.getBitmapSurface(&image);
|
||||
mBitmapOut->getBitmapSurface(&image);
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
hw.copyBackToImage(image);
|
||||
|
||||
@@ -194,7 +185,7 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut
|
||||
copybit_image_t dst;
|
||||
const GraphicPlane& plane(graphicPlane(0));
|
||||
const DisplayHardware& hw(plane.displayHardware());
|
||||
hw.getDisplaySurface(&dst);
|
||||
//hw.getDisplaySurface(&dst);
|
||||
|
||||
// clear screen
|
||||
// TODO: with update on demand, we may be able
|
||||
@@ -212,10 +203,10 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut
|
||||
}
|
||||
|
||||
copybit_image_t src;
|
||||
mBitmapIn.getBitmapSurface(&src);
|
||||
mBitmapIn->getBitmapSurface(&src);
|
||||
|
||||
copybit_image_t srcOut;
|
||||
mBitmapOut.getBitmapSurface(&srcOut);
|
||||
mBitmapOut->getBitmapSurface(&srcOut);
|
||||
|
||||
const int w = dst.w*scale;
|
||||
const int h = dst.h*scale;
|
||||
@@ -225,78 +216,54 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut
|
||||
const copybit_rect_t srect = { 0, 0, src.w, src.h };
|
||||
const Region reg(Rect( drect.l, drect.t, drect.r, drect.b ));
|
||||
|
||||
int err = NO_ERROR;
|
||||
const int can_use_copybit = canUseCopybit();
|
||||
if (can_use_copybit) {
|
||||
copybit_device_t* copybit = mFlinger->getBlitEngine();
|
||||
copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
|
||||
copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
|
||||
|
||||
if (alphaIn > 0) {
|
||||
region_iterator it(reg);
|
||||
copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_ENABLE);
|
||||
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaIn*255));
|
||||
err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
|
||||
}
|
||||
GGLSurface t;
|
||||
t.version = sizeof(GGLSurface);
|
||||
t.width = src.w;
|
||||
t.height = src.h;
|
||||
t.stride = src.w;
|
||||
t.vstride= src.h;
|
||||
t.format = src.format;
|
||||
t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
|
||||
|
||||
if (!err && alphaOut > 0.0f) {
|
||||
region_iterator it(reg);
|
||||
copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE);
|
||||
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaOut*255));
|
||||
err = copybit->stretch(copybit, &dst, &srcOut, &drect, &srect, &it);
|
||||
}
|
||||
LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err));
|
||||
Transform tr;
|
||||
tr.set(scale,0,0,scale);
|
||||
tr.set(xc, yc);
|
||||
|
||||
// FIXME: we should not access mVertices and mDrawingState like that,
|
||||
// but since we control the animation, we know it's going to work okay.
|
||||
// eventually we'd need a more formal way of doing things like this.
|
||||
LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this));
|
||||
tr.transform(self.mVertices[0], 0, 0);
|
||||
tr.transform(self.mVertices[1], 0, src.h);
|
||||
tr.transform(self.mVertices[2], src.w, src.h);
|
||||
tr.transform(self.mVertices[3], src.w, 0);
|
||||
if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
|
||||
// Too slow to do this in software
|
||||
self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter;
|
||||
}
|
||||
if (!can_use_copybit || err) {
|
||||
GGLSurface t;
|
||||
t.version = sizeof(GGLSurface);
|
||||
t.width = src.w;
|
||||
t.height = src.h;
|
||||
t.stride = src.w;
|
||||
t.vstride= src.h;
|
||||
t.format = src.format;
|
||||
|
||||
if (alphaIn > 0.0f) {
|
||||
t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
|
||||
|
||||
Transform tr;
|
||||
tr.set(scale,0,0,scale);
|
||||
tr.set(xc, yc);
|
||||
|
||||
// FIXME: we should not access mVertices and mDrawingState like that,
|
||||
// but since we control the animation, we know it's going to work okay.
|
||||
// eventually we'd need a more formal way of doing things like this.
|
||||
LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this));
|
||||
tr.transform(self.mVertices[0], 0, 0);
|
||||
tr.transform(self.mVertices[1], 0, src.h);
|
||||
tr.transform(self.mVertices[2], src.w, src.h);
|
||||
tr.transform(self.mVertices[3], src.w, 0);
|
||||
if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
|
||||
// Too slow to do this in software
|
||||
self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter;
|
||||
if (UNLIKELY(mTextureNameIn == -1LU)) {
|
||||
mTextureNameIn = createTexture();
|
||||
GLuint w=0, h=0;
|
||||
const Region dirty(Rect(t.width, t.height));
|
||||
loadTexture(dirty, mTextureNameIn, t, w, h);
|
||||
}
|
||||
self.mDrawingState.alpha = int(alphaIn*255);
|
||||
drawWithOpenGL(reg, mTextureNameIn, t);
|
||||
}
|
||||
|
||||
if (alphaIn > 0.0f) {
|
||||
t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
|
||||
if (UNLIKELY(mTextureNameIn == -1LU)) {
|
||||
mTextureNameIn = createTexture();
|
||||
GLuint w=0, h=0;
|
||||
const Region dirty(Rect(t.width, t.height));
|
||||
loadTexture(dirty, mTextureNameIn, t, w, h);
|
||||
}
|
||||
self.mDrawingState.alpha = int(alphaIn*255);
|
||||
drawWithOpenGL(reg, mTextureNameIn, t);
|
||||
}
|
||||
|
||||
if (alphaOut > 0.0f) {
|
||||
t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset);
|
||||
if (UNLIKELY(mTextureName == -1LU)) {
|
||||
mTextureName = createTexture();
|
||||
GLuint w=0, h=0;
|
||||
const Region dirty(Rect(t.width, t.height));
|
||||
loadTexture(dirty, mTextureName, t, w, h);
|
||||
}
|
||||
self.mDrawingState.alpha = int(alphaOut*255);
|
||||
drawWithOpenGL(reg, mTextureName, t);
|
||||
if (alphaOut > 0.0f) {
|
||||
t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset);
|
||||
if (UNLIKELY(mTextureName == -1LU)) {
|
||||
mTextureName = createTexture();
|
||||
GLuint w=0, h=0;
|
||||
const Region dirty(Rect(t.width, t.height));
|
||||
loadTexture(dirty, mTextureName, t, w, h);
|
||||
}
|
||||
self.mDrawingState.alpha = int(alphaOut*255);
|
||||
drawWithOpenGL(reg, mTextureName, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@ public:
|
||||
|
||||
LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display,
|
||||
OrientationAnimation* anim,
|
||||
const LayerBitmap& bitmapIn,
|
||||
const LayerBitmap& bitmapOut);
|
||||
const sp<Buffer>& bitmapIn,
|
||||
const sp<Buffer>& bitmapOut);
|
||||
virtual ~LayerOrientationAnim();
|
||||
|
||||
void onOrientationCompleted();
|
||||
@@ -90,8 +90,8 @@ private:
|
||||
};
|
||||
|
||||
OrientationAnimation* mAnim;
|
||||
LayerBitmap mBitmapIn;
|
||||
LayerBitmap mBitmapOut;
|
||||
sp<Buffer> mBitmapIn;
|
||||
sp<Buffer> mBitmapOut;
|
||||
nsecs_t mStartTime;
|
||||
nsecs_t mFinishTime;
|
||||
bool mOrientationCompleted;
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <core/SkBitmap.h>
|
||||
|
||||
#include <ui/EGLDisplaySurface.h>
|
||||
|
||||
#include "LayerBase.h"
|
||||
#include "LayerOrientationAnim.h"
|
||||
#include "LayerOrientationAnimRotate.h"
|
||||
@@ -51,10 +47,10 @@ const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI;
|
||||
LayerOrientationAnimRotate::LayerOrientationAnimRotate(
|
||||
SurfaceFlinger* flinger, DisplayID display,
|
||||
OrientationAnimation* anim,
|
||||
const LayerBitmap& bitmap,
|
||||
const LayerBitmap& bitmapIn)
|
||||
const sp<Buffer>& bitmapIn,
|
||||
const sp<Buffer>& bitmapOut)
|
||||
: LayerOrientationAnimBase(flinger, display), mAnim(anim),
|
||||
mBitmap(bitmap), mBitmapIn(bitmapIn),
|
||||
mBitmapIn(bitmapIn), mBitmapOut(bitmapOut),
|
||||
mTextureName(-1), mTextureNameIn(-1)
|
||||
{
|
||||
mStartTime = systemTime();
|
||||
@@ -103,7 +99,6 @@ void LayerOrientationAnimRotate::validateVisibility(const Transform&)
|
||||
mTop = tr.ty();
|
||||
transparentRegionScreen.clear();
|
||||
mTransformed = true;
|
||||
mCanUseCopyBit = false;
|
||||
}
|
||||
|
||||
void LayerOrientationAnimRotate::onOrientationCompleted()
|
||||
@@ -126,7 +121,7 @@ void LayerOrientationAnimRotate::onDraw(const Region& clip) const
|
||||
if (mFirstRedraw) {
|
||||
// make a copy of what's on screen
|
||||
copybit_image_t image;
|
||||
mBitmapIn.getBitmapSurface(&image);
|
||||
mBitmapIn->getBitmapSurface(&image);
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
hw.copyBackToImage(image);
|
||||
|
||||
@@ -185,7 +180,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const
|
||||
copybit_image_t dst;
|
||||
const GraphicPlane& plane(graphicPlane(0));
|
||||
const DisplayHardware& hw(plane.displayHardware());
|
||||
hw.getDisplaySurface(&dst);
|
||||
//hw.getDisplaySurface(&dst);
|
||||
|
||||
// clear screen
|
||||
// TODO: with update on demand, we may be able
|
||||
@@ -200,7 +195,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const
|
||||
const int h = dst.h;
|
||||
|
||||
copybit_image_t src;
|
||||
mBitmap.getBitmapSurface(&src);
|
||||
mBitmapIn->getBitmapSurface(&src);
|
||||
const copybit_rect_t srect = { 0, 0, src.w, src.h };
|
||||
|
||||
|
||||
@@ -255,7 +250,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const
|
||||
tr.transform(self.mVertices[3], src.w, 0);
|
||||
|
||||
copybit_image_t src;
|
||||
mBitmapIn.getBitmapSurface(&src);
|
||||
mBitmapIn->getBitmapSurface(&src);
|
||||
t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
|
||||
if (UNLIKELY(mTextureNameIn == -1LU)) {
|
||||
mTextureNameIn = createTexture();
|
||||
|
||||
@@ -40,8 +40,8 @@ public:
|
||||
|
||||
LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display,
|
||||
OrientationAnimation* anim,
|
||||
const LayerBitmap& zoomOut,
|
||||
const LayerBitmap& zoomIn);
|
||||
const sp<Buffer>& bitmapIn,
|
||||
const sp<Buffer>& bitmapOut);
|
||||
virtual ~LayerOrientationAnimRotate();
|
||||
|
||||
void onOrientationCompleted();
|
||||
@@ -55,8 +55,8 @@ private:
|
||||
void drawScaled(float angle, float scale, float alpha) const;
|
||||
|
||||
OrientationAnimation* mAnim;
|
||||
LayerBitmap mBitmap;
|
||||
LayerBitmap mBitmapIn;
|
||||
sp<Buffer> mBitmapIn;
|
||||
sp<Buffer> mBitmapOut;
|
||||
nsecs_t mStartTime;
|
||||
nsecs_t mFinishTime;
|
||||
bool mOrientationCompleted;
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
@@ -24,7 +22,6 @@
|
||||
#include "LayerOrientationAnimRotate.h"
|
||||
#include "OrientationAnimation.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "VRamHeap.h"
|
||||
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
|
||||
@@ -35,9 +32,6 @@ namespace android {
|
||||
OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger)
|
||||
: mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE)
|
||||
{
|
||||
// allocate a memory-dealer for this the first time
|
||||
mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap(
|
||||
ISurfaceComposer::eHardware);
|
||||
}
|
||||
|
||||
OrientationAnimation::~OrientationAnimation()
|
||||
@@ -98,19 +92,14 @@ bool OrientationAnimation::prepare()
|
||||
const uint32_t w = hw.getWidth();
|
||||
const uint32_t h = hw.getHeight();
|
||||
|
||||
LayerBitmap bitmap;
|
||||
bitmap.init(mTemporaryDealer);
|
||||
bitmap.setBits(w, h, 1, hw.getFormat());
|
||||
|
||||
LayerBitmap bitmapIn;
|
||||
bitmapIn.init(mTemporaryDealer);
|
||||
bitmapIn.setBits(w, h, 1, hw.getFormat());
|
||||
sp<Buffer> bitmap = new Buffer(w, h, hw.getFormat());
|
||||
sp<Buffer> bitmapIn = new Buffer(w, h, hw.getFormat());
|
||||
|
||||
copybit_image_t front;
|
||||
bitmap.getBitmapSurface(&front);
|
||||
hw.copyFrontToImage(front);
|
||||
bitmap->getBitmapSurface(&front);
|
||||
hw.copyFrontToImage(front); // FIXME: we need an extension to do this
|
||||
|
||||
LayerOrientationAnimBase* l;
|
||||
sp<LayerOrientationAnimBase> l;
|
||||
|
||||
if (mType & 0x80) {
|
||||
l = new LayerOrientationAnimRotate(
|
||||
@@ -152,7 +141,7 @@ bool OrientationAnimation::finished()
|
||||
{
|
||||
mState = DONE;
|
||||
mFlinger->removeLayer(mLayerOrientationAnim);
|
||||
mLayerOrientationAnim = NULL;
|
||||
mLayerOrientationAnim.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,8 +72,7 @@ private:
|
||||
bool finished();
|
||||
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
sp<MemoryDealer> mTemporaryDealer;
|
||||
LayerOrientationAnimBase* mLayerOrientationAnim;
|
||||
sp< LayerOrientationAnimBase > mLayerOrientationAnim;
|
||||
int mState;
|
||||
uint32_t mType;
|
||||
};
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -40,12 +38,12 @@
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/EGLDisplaySurface.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include "clz.h"
|
||||
#include "BufferAllocator.h"
|
||||
#include "CPUGauge.h"
|
||||
#include "Layer.h"
|
||||
#include "LayerBlur.h"
|
||||
@@ -55,10 +53,8 @@
|
||||
#include "LayerOrientationAnim.h"
|
||||
#include "OrientationAnimation.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "VRamHeap.h"
|
||||
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
#include "GPUHardware/GPUHardware.h"
|
||||
|
||||
|
||||
#define DISPLAY_COUNT 1
|
||||
@@ -86,30 +82,30 @@ SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs)
|
||||
}
|
||||
|
||||
ssize_t SurfaceFlinger::LayerVector::indexOf(
|
||||
LayerBase* key, size_t guess) const
|
||||
const sp<LayerBase>& key, size_t guess) const
|
||||
{
|
||||
if (guess<size() && lookup.keyAt(guess) == key)
|
||||
return guess;
|
||||
const ssize_t i = lookup.indexOfKey(key);
|
||||
if (i>=0) {
|
||||
const size_t idx = lookup.valueAt(i);
|
||||
LOG_ASSERT(layers[idx]==key,
|
||||
LOGE_IF(layers[idx]!=key,
|
||||
"LayerVector[%p]: layers[%d]=%p, key=%p",
|
||||
this, int(idx), layers[idx], key);
|
||||
this, int(idx), layers[idx].get(), key.get());
|
||||
return idx;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
ssize_t SurfaceFlinger::LayerVector::add(
|
||||
LayerBase* layer,
|
||||
Vector<LayerBase*>::compar_t cmp)
|
||||
const sp<LayerBase>& layer,
|
||||
Vector< sp<LayerBase> >::compar_t cmp)
|
||||
{
|
||||
size_t count = layers.size();
|
||||
ssize_t l = 0;
|
||||
ssize_t h = count-1;
|
||||
ssize_t mid;
|
||||
LayerBase* const* a = layers.array();
|
||||
sp<LayerBase> const* a = layers.array();
|
||||
while (l <= h) {
|
||||
mid = l + (h - l)/2;
|
||||
const int c = cmp(a+mid, &layer);
|
||||
@@ -132,14 +128,14 @@ ssize_t SurfaceFlinger::LayerVector::add(
|
||||
return order;
|
||||
}
|
||||
|
||||
ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer)
|
||||
ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer)
|
||||
{
|
||||
const ssize_t keyIndex = lookup.indexOfKey(layer);
|
||||
if (keyIndex >= 0) {
|
||||
const size_t index = lookup.valueAt(keyIndex);
|
||||
LOG_ASSERT(layers[index]==layer,
|
||||
LOGE_IF(layers[index]!=layer,
|
||||
"LayerVector[%p]: layers[%u]=%p, layer=%p",
|
||||
this, int(index), layers[index], layer);
|
||||
this, int(index), layers[index].get(), layer.get());
|
||||
layers.removeItemsAt(index);
|
||||
lookup.removeItemsAt(keyIndex);
|
||||
const size_t count = lookup.size();
|
||||
@@ -154,8 +150,8 @@ ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer)
|
||||
}
|
||||
|
||||
ssize_t SurfaceFlinger::LayerVector::reorder(
|
||||
LayerBase* layer,
|
||||
Vector<LayerBase*>::compar_t cmp)
|
||||
const sp<LayerBase>& layer,
|
||||
Vector< sp<LayerBase> >::compar_t cmp)
|
||||
{
|
||||
// XXX: it's a little lame. but oh well...
|
||||
ssize_t err = remove(layer);
|
||||
@@ -173,6 +169,7 @@ SurfaceFlinger::SurfaceFlinger()
|
||||
: BnSurfaceComposer(), Thread(false),
|
||||
mTransactionFlags(0),
|
||||
mTransactionCount(0),
|
||||
mLayersRemoved(false),
|
||||
mBootTime(systemTime()),
|
||||
mLastScheduledBroadcast(NULL),
|
||||
mVisibleRegionsDirty(false),
|
||||
@@ -223,11 +220,6 @@ SurfaceFlinger::~SurfaceFlinger()
|
||||
delete mOrientationAnimation;
|
||||
}
|
||||
|
||||
copybit_device_t* SurfaceFlinger::getBlitEngine() const
|
||||
{
|
||||
return graphicPlane(0).displayHardware().getBlitEngine();
|
||||
}
|
||||
|
||||
overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
|
||||
{
|
||||
return graphicPlane(0).displayHardware().getOverlayEngine();
|
||||
@@ -238,20 +230,6 @@ sp<IMemory> SurfaceFlinger::getCblk() const
|
||||
return mServerCblkMemory;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback,
|
||||
gpu_info_t* gpu)
|
||||
{
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
const int pid = ipc->getCallingPid();
|
||||
status_t err = mGPU->request(pid, callback, gpu);
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::revokeGPU()
|
||||
{
|
||||
return mGPU->friendlyRevoke();
|
||||
}
|
||||
|
||||
sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
|
||||
{
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
@@ -279,11 +257,13 @@ void SurfaceFlinger::destroyConnection(ClientID cid)
|
||||
Client* const client = mClientsMap.valueFor(cid);
|
||||
if (client) {
|
||||
// free all the layers this client owns
|
||||
const Vector<LayerBaseClient*>& layers = client->getLayers();
|
||||
const Vector< wp<LayerBaseClient> >& layers = client->getLayers();
|
||||
const size_t count = layers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
LayerBaseClient* const layer = layers[i];
|
||||
removeLayer_l(layer);
|
||||
sp<LayerBaseClient> layer(layers[i].promote());
|
||||
if (layer != 0) {
|
||||
removeLayer_l(layer);
|
||||
}
|
||||
}
|
||||
|
||||
// the resources associated with this client will be freed
|
||||
@@ -338,9 +318,6 @@ static inline uint16_t pack565(int r, int g, int b) {
|
||||
return (r<<11)|(g<<5)|b;
|
||||
}
|
||||
|
||||
// this is defined in libGLES_CM.so
|
||||
extern ISurfaceComposer* GLES_localSurfaceManager;
|
||||
|
||||
status_t SurfaceFlinger::readyToRun()
|
||||
{
|
||||
LOGI( "SurfaceFlinger's main thread ready to run. "
|
||||
@@ -357,17 +334,6 @@ status_t SurfaceFlinger::readyToRun()
|
||||
LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
|
||||
new(mServerCblk) surface_flinger_cblk_t;
|
||||
|
||||
// get a reference to the GPU if we have one
|
||||
mGPU = GPUFactory::getGPU();
|
||||
|
||||
// create the surface Heap manager, which manages the heaps
|
||||
// (be it in RAM or VRAM) where surfaces are allocated
|
||||
// We give 8 MB per client.
|
||||
mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20);
|
||||
|
||||
|
||||
GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this);
|
||||
|
||||
// we only support one display currently
|
||||
int dpy = 0;
|
||||
|
||||
@@ -597,13 +563,11 @@ void SurfaceFlinger::handleConsoleEvents()
|
||||
if (mDeferReleaseConsole && hw.canDraw()) {
|
||||
// We got the release signal before the aquire signal
|
||||
mDeferReleaseConsole = false;
|
||||
revokeGPU();
|
||||
hw.releaseScreen();
|
||||
}
|
||||
|
||||
if (what & eConsoleReleased) {
|
||||
if (hw.canDraw()) {
|
||||
revokeGPU();
|
||||
hw.releaseScreen();
|
||||
} else {
|
||||
mDeferReleaseConsole = true;
|
||||
@@ -628,7 +592,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
||||
const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
|
||||
if (layersNeedTransaction) {
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
LayerBase* const layer = currentLayers[i];
|
||||
const sp<LayerBase>& layer = currentLayers[i];
|
||||
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
|
||||
if (!trFlags) continue;
|
||||
|
||||
@@ -685,8 +649,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
||||
|
||||
// some layers might have been removed, so
|
||||
// we need to update the regions they're exposing.
|
||||
size_t c = mRemovedLayers.size();
|
||||
if (c) {
|
||||
if (mLayersRemoved) {
|
||||
mVisibleRegionsDirty = true;
|
||||
}
|
||||
|
||||
@@ -723,7 +686,7 @@ void SurfaceFlinger::computeVisibleRegions(
|
||||
|
||||
size_t i = currentLayers.size();
|
||||
while (i--) {
|
||||
LayerBase* const layer = currentLayers[i];
|
||||
const sp<LayerBase>& layer = currentLayers[i];
|
||||
layer->validateVisibility(planeTransform);
|
||||
|
||||
// start with the whole surface at its current location
|
||||
@@ -823,9 +786,9 @@ bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
|
||||
{
|
||||
bool recomputeVisibleRegions = false;
|
||||
size_t count = currentLayers.size();
|
||||
LayerBase* const* layers = currentLayers.array();
|
||||
sp<LayerBase> const* layers = currentLayers.array();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
LayerBase* const layer = layers[i];
|
||||
const sp<LayerBase>& layer = layers[i];
|
||||
layer->lockPageFlip(recomputeVisibleRegions);
|
||||
}
|
||||
return recomputeVisibleRegions;
|
||||
@@ -836,9 +799,9 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
|
||||
const GraphicPlane& plane(graphicPlane(0));
|
||||
const Transform& planeTransform(plane.transform());
|
||||
size_t count = currentLayers.size();
|
||||
LayerBase* const* layers = currentLayers.array();
|
||||
sp<LayerBase> const* layers = currentLayers.array();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
LayerBase* const layer = layers[i];
|
||||
const sp<LayerBase>& layer = layers[i];
|
||||
layer->unlockPageFlip(planeTransform, mDirtyRegion);
|
||||
}
|
||||
}
|
||||
@@ -889,9 +852,9 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
|
||||
const SurfaceFlinger& flinger(*this);
|
||||
const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
|
||||
const size_t count = drawingLayers.size();
|
||||
LayerBase const* const* const layers = drawingLayers.array();
|
||||
sp<LayerBase> const* const layers = drawingLayers.array();
|
||||
for (size_t i=0 ; i<count ; ++i) {
|
||||
LayerBase const * const layer = layers[i];
|
||||
const sp<LayerBase>& layer = layers[i];
|
||||
const Region& visibleRegion(layer->visibleRegionScreen);
|
||||
if (!visibleRegion.isEmpty()) {
|
||||
const Region clip(dirty.intersect(visibleRegion));
|
||||
@@ -906,9 +869,9 @@ void SurfaceFlinger::unlockClients()
|
||||
{
|
||||
const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
|
||||
const size_t count = drawingLayers.size();
|
||||
LayerBase* const* const layers = drawingLayers.array();
|
||||
sp<LayerBase> const* const layers = drawingLayers.array();
|
||||
for (size_t i=0 ; i<count ; ++i) {
|
||||
LayerBase* const layer = layers[i];
|
||||
const sp<LayerBase>& layer = layers[i];
|
||||
layer->finishPageFlip();
|
||||
}
|
||||
}
|
||||
@@ -1051,7 +1014,7 @@ void SurfaceFlinger::debugShowFPS() const
|
||||
// XXX: mFPS has the value we want
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::addLayer(LayerBase* layer)
|
||||
status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
|
||||
{
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
addLayer_l(layer);
|
||||
@@ -1059,7 +1022,7 @@ status_t SurfaceFlinger::addLayer(LayerBase* layer)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::removeLayer(LayerBase* layer)
|
||||
status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
|
||||
{
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
removeLayer_l(layer);
|
||||
@@ -1067,32 +1030,31 @@ status_t SurfaceFlinger::removeLayer(LayerBase* layer)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer)
|
||||
status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
|
||||
{
|
||||
layer->forceVisibilityTransaction();
|
||||
setTransactionFlags(eTraversalNeeded);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::addLayer_l(LayerBase* layer)
|
||||
status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
|
||||
{
|
||||
ssize_t i = mCurrentState.layersSortedByZ.add(
|
||||
layer, &LayerBase::compareCurrentStateZ);
|
||||
LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer);
|
||||
if (lbc) {
|
||||
sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
|
||||
if (lbc != 0) {
|
||||
mLayerMap.add(lbc->serverIndex(), lbc);
|
||||
}
|
||||
mRemovedLayers.remove(layer);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase)
|
||||
status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
|
||||
{
|
||||
ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
|
||||
if (index >= 0) {
|
||||
mRemovedLayers.add(layerBase);
|
||||
LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase);
|
||||
if (layer) {
|
||||
mLayersRemoved = true;
|
||||
sp<LayerBaseClient> layer = LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
|
||||
if (layer != 0) {
|
||||
mLayerMap.removeItem(layer->serverIndex());
|
||||
}
|
||||
return NO_ERROR;
|
||||
@@ -1107,8 +1069,8 @@ status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase)
|
||||
void SurfaceFlinger::free_resources_l()
|
||||
{
|
||||
// Destroy layers that were removed
|
||||
destroy_all_removed_layers_l();
|
||||
|
||||
mLayersRemoved = false;
|
||||
|
||||
// free resources associated with disconnected clients
|
||||
SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
|
||||
Vector<Client*>& disconnectedClients(mDisconnectedClients);
|
||||
@@ -1128,22 +1090,6 @@ void SurfaceFlinger::free_resources_l()
|
||||
disconnectedClients.clear();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::destroy_all_removed_layers_l()
|
||||
{
|
||||
size_t c = mRemovedLayers.size();
|
||||
while (c--) {
|
||||
LayerBase* const removed_layer = mRemovedLayers[c];
|
||||
|
||||
LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0,
|
||||
"layer %p removed but still in the current state list",
|
||||
removed_layer);
|
||||
|
||||
delete removed_layer;
|
||||
}
|
||||
mRemovedLayers.clear();
|
||||
}
|
||||
|
||||
|
||||
uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
|
||||
{
|
||||
return android_atomic_and(~flags, &mTransactionFlags) & flags;
|
||||
@@ -1227,7 +1173,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
|
||||
DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
|
||||
uint32_t flags)
|
||||
{
|
||||
LayerBaseClient* layer = 0;
|
||||
sp<LayerBaseClient> layer;
|
||||
sp<LayerBaseClient::Surface> surfaceHandle;
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
Client* const c = mClientsMap.valueFor(clientId);
|
||||
@@ -1259,7 +1205,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
|
||||
break;
|
||||
}
|
||||
|
||||
if (layer) {
|
||||
if (layer != 0) {
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
surfaceHandle = layer->getSurface();
|
||||
if (surfaceHandle != 0)
|
||||
@@ -1269,7 +1215,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
|
||||
return surfaceHandle;
|
||||
}
|
||||
|
||||
LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
|
||||
sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
|
||||
Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
|
||||
{
|
||||
@@ -1284,44 +1230,43 @@ LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
|
||||
break;
|
||||
}
|
||||
|
||||
Layer* layer = new Layer(this, display, client, id);
|
||||
sp<Layer> layer = new Layer(this, display, client, id);
|
||||
status_t err = layer->setBuffers(client, w, h, format, flags);
|
||||
if (LIKELY(err == NO_ERROR)) {
|
||||
layer->initStates(w, h, flags);
|
||||
addLayer_l(layer);
|
||||
} else {
|
||||
LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
|
||||
delete layer;
|
||||
return 0;
|
||||
layer.clear();
|
||||
}
|
||||
return layer;
|
||||
}
|
||||
|
||||
LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked(
|
||||
sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
|
||||
Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h, uint32_t flags)
|
||||
{
|
||||
LayerBlur* layer = new LayerBlur(this, display, client, id);
|
||||
sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
|
||||
layer->initStates(w, h, flags);
|
||||
addLayer_l(layer);
|
||||
return layer;
|
||||
}
|
||||
|
||||
LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked(
|
||||
sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
|
||||
Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h, uint32_t flags)
|
||||
{
|
||||
LayerDim* layer = new LayerDim(this, display, client, id);
|
||||
sp<LayerDim> layer = new LayerDim(this, display, client, id);
|
||||
layer->initStates(w, h, flags);
|
||||
addLayer_l(layer);
|
||||
return layer;
|
||||
}
|
||||
|
||||
LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked(
|
||||
sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
|
||||
Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h, uint32_t flags)
|
||||
{
|
||||
LayerBuffer* layer = new LayerBuffer(this, display, client, id);
|
||||
sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id);
|
||||
layer->initStates(w, h, flags);
|
||||
addLayer_l(layer);
|
||||
return layer;
|
||||
@@ -1330,7 +1275,7 @@ LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked(
|
||||
status_t SurfaceFlinger::destroySurface(SurfaceID index)
|
||||
{
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
LayerBaseClient* const layer = getLayerUser_l(index);
|
||||
const sp<LayerBaseClient>& layer = getLayerUser_l(index);
|
||||
status_t err = removeLayer_l(layer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -1348,8 +1293,8 @@ status_t SurfaceFlinger::setClientState(
|
||||
cid <<= 16;
|
||||
for (int i=0 ; i<count ; i++) {
|
||||
const layer_state_t& s = states[i];
|
||||
LayerBaseClient* layer = getLayerUser_l(s.surface | cid);
|
||||
if (layer) {
|
||||
const sp<LayerBaseClient>& layer = getLayerUser_l(s.surface | cid);
|
||||
if (layer != 0) {
|
||||
const uint32_t what = s.what;
|
||||
// check if it has been destroyed first
|
||||
if (what & eDestroyed) {
|
||||
@@ -1401,9 +1346,10 @@ status_t SurfaceFlinger::setClientState(
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const
|
||||
sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
|
||||
{
|
||||
return mLayerMap.valueFor(s);
|
||||
sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
|
||||
return layer;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::screenReleased(int dpy)
|
||||
@@ -1446,7 +1392,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||
const size_t count = currentLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
/*** LayerBase ***/
|
||||
LayerBase const * const layer = currentLayers[i];
|
||||
const sp<LayerBase>& layer = currentLayers[i];
|
||||
const Layer::State& s = layer->drawingState();
|
||||
snprintf(buffer, SIZE,
|
||||
"+ %s %p\n"
|
||||
@@ -1454,7 +1400,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||
"z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
|
||||
"needsBlending=%1d, invalidate=%1d, "
|
||||
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
|
||||
layer->getTypeID(), layer,
|
||||
layer->getTypeID(), layer.get(),
|
||||
s.z, layer->tx(), layer->ty(), s.w, s.h,
|
||||
layer->needsBlending(), layer->contentDirty,
|
||||
s.alpha, s.flags,
|
||||
@@ -1463,9 +1409,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||
result.append(buffer);
|
||||
buffer[0] = 0;
|
||||
/*** LayerBaseClient ***/
|
||||
LayerBaseClient* const lbc =
|
||||
LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer);
|
||||
if (lbc) {
|
||||
sp<LayerBaseClient> lbc =
|
||||
LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
|
||||
if (lbc != 0) {
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
"id=0x%08x, client=0x%08x, identity=%u\n",
|
||||
@@ -1475,18 +1421,20 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||
result.append(buffer);
|
||||
buffer[0] = 0;
|
||||
/*** Layer ***/
|
||||
Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer);
|
||||
if (l) {
|
||||
sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
|
||||
if (l != 0) {
|
||||
const LayerBitmap& buf0(l->getBuffer(0));
|
||||
const LayerBitmap& buf1(l->getBuffer(1));
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
"format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d,"
|
||||
"format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
|
||||
" freezeLock=%p, swapState=0x%08x\n",
|
||||
l->pixelFormat(),
|
||||
buf0.width(), buf0.height(), buf0.stride(),
|
||||
buf1.width(), buf1.height(), buf1.stride(),
|
||||
l->getTextureName(), l->getFreezeLock().get(),
|
||||
buf0.getWidth(), buf0.getHeight(),
|
||||
buf0.getBuffer()->getStride(),
|
||||
buf1.getWidth(), buf1.getHeight(),
|
||||
buf1.getBuffer()->getStride(),
|
||||
l->getFreezeLock().get(),
|
||||
l->lcblk->swapState);
|
||||
}
|
||||
result.append(buffer);
|
||||
@@ -1503,19 +1451,8 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||
mCurrentState.orientation, hw.canDraw());
|
||||
result.append(buffer);
|
||||
|
||||
sp<AllocatorInterface> allocator;
|
||||
if (mGPU != 0) {
|
||||
snprintf(buffer, SIZE, " GPU owner: %d\n", mGPU->getOwner());
|
||||
result.append(buffer);
|
||||
allocator = mGPU->getAllocator();
|
||||
if (allocator != 0) {
|
||||
allocator->dump(result, "GPU Allocator");
|
||||
}
|
||||
}
|
||||
allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM);
|
||||
if (allocator != 0) {
|
||||
allocator->dump(result, "PMEM Allocator");
|
||||
}
|
||||
const BufferAllocator& alloc(BufferAllocator::get());
|
||||
alloc.dump(result);
|
||||
}
|
||||
write(fd, result.string(), result.size());
|
||||
return NO_ERROR;
|
||||
@@ -1532,7 +1469,6 @@ status_t SurfaceFlinger::onTransact(
|
||||
case FREEZE_DISPLAY:
|
||||
case UNFREEZE_DISPLAY:
|
||||
case BOOT_FINISHED:
|
||||
case REVOKE_GPU:
|
||||
{
|
||||
// codes that require permission check
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
@@ -1599,12 +1535,6 @@ status_t SurfaceFlinger::onTransact(
|
||||
signalEvent();
|
||||
}
|
||||
return NO_ERROR;
|
||||
case 1005: // ask GPU revoke
|
||||
mGPU->friendlyRevoke();
|
||||
return NO_ERROR;
|
||||
case 1006: // revoke GPU
|
||||
mGPU->unconditionalRevoke();
|
||||
return NO_ERROR;
|
||||
case 1007: // set mFreezeCount
|
||||
mFreezeCount = data.readInt32();
|
||||
return NO_ERROR;
|
||||
@@ -1633,7 +1563,6 @@ status_t SurfaceFlinger::onTransact(
|
||||
Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
|
||||
: ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
|
||||
{
|
||||
mSharedHeapAllocator = getSurfaceHeapManager()->createHeap();
|
||||
const int pgsize = getpagesize();
|
||||
const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
|
||||
mCblkHeap = new MemoryDealer(cblksize);
|
||||
@@ -1653,10 +1582,6 @@ Client::~Client() {
|
||||
}
|
||||
}
|
||||
|
||||
const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const {
|
||||
return mFlinger->getSurfaceHeapManager();
|
||||
}
|
||||
|
||||
int32_t Client::generateId(int pid)
|
||||
{
|
||||
const uint32_t i = clz( ~mBitmap );
|
||||
@@ -1668,13 +1593,15 @@ int32_t Client::generateId(int pid)
|
||||
mBitmap |= 1<<(31-i);
|
||||
return i;
|
||||
}
|
||||
status_t Client::bindLayer(LayerBaseClient* layer, int32_t id)
|
||||
|
||||
status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id)
|
||||
{
|
||||
ssize_t idx = mInUse.indexOf(id);
|
||||
if (idx < 0)
|
||||
return NAME_NOT_FOUND;
|
||||
return mLayers.insertAt(layer, idx);
|
||||
}
|
||||
|
||||
void Client::free(int32_t id)
|
||||
{
|
||||
ssize_t idx = mInUse.remove(uint8_t(id));
|
||||
@@ -1684,27 +1611,18 @@ void Client::free(int32_t id)
|
||||
}
|
||||
}
|
||||
|
||||
sp<MemoryDealer> Client::createAllocator(uint32_t flags)
|
||||
{
|
||||
sp<MemoryDealer> allocator;
|
||||
allocator = getSurfaceHeapManager()->createHeap(
|
||||
flags, getClientPid(), mSharedHeapAllocator);
|
||||
return allocator;
|
||||
}
|
||||
|
||||
bool Client::isValid(int32_t i) const {
|
||||
return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
|
||||
}
|
||||
const uint8_t* Client::inUseArray() const {
|
||||
return mInUse.array();
|
||||
}
|
||||
size_t Client::numActiveLayers() const {
|
||||
return mInUse.size();
|
||||
}
|
||||
LayerBaseClient* Client::getLayerUser(int32_t i) const {
|
||||
|
||||
sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
|
||||
sp<LayerBaseClient> lbc;
|
||||
ssize_t idx = mInUse.indexOf(uint8_t(i));
|
||||
if (idx<0) return 0;
|
||||
return mLayers[idx];
|
||||
if (idx >= 0) {
|
||||
lbc = mLayers[idx].promote();
|
||||
LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx));
|
||||
}
|
||||
return lbc;
|
||||
}
|
||||
|
||||
void Client::dump(const char* what)
|
||||
@@ -1841,6 +1759,10 @@ const Transform& GraphicPlane::transform() const {
|
||||
return mGlobalTransform;
|
||||
}
|
||||
|
||||
EGLDisplay GraphicPlane::getEGLDisplay() const {
|
||||
return mHw->getEGLDisplay();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <utils/Atomic.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/MemoryDealer.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/ISurfaceComposer.h>
|
||||
@@ -52,13 +53,10 @@ class Client;
|
||||
class BClient;
|
||||
class DisplayHardware;
|
||||
class FreezeLock;
|
||||
class GPUHardwareInterface;
|
||||
class IGPUCallback;
|
||||
class Layer;
|
||||
class LayerBuffer;
|
||||
class LayerOrientationAnim;
|
||||
class OrientationAnimation;
|
||||
class SurfaceHeapManager;
|
||||
|
||||
typedef int32_t ClientID;
|
||||
|
||||
@@ -75,17 +73,13 @@ public:
|
||||
|
||||
int32_t generateId(int pid);
|
||||
void free(int32_t id);
|
||||
status_t bindLayer(LayerBaseClient* layer, int32_t id);
|
||||
sp<MemoryDealer> createAllocator(uint32_t memory_type);
|
||||
status_t bindLayer(const sp<LayerBaseClient>& layer, int32_t id);
|
||||
|
||||
inline bool isValid(int32_t i) const;
|
||||
inline const uint8_t* inUseArray() const;
|
||||
inline size_t numActiveLayers() const;
|
||||
LayerBaseClient* getLayerUser(int32_t i) const;
|
||||
const Vector<LayerBaseClient*>& getLayers() const { return mLayers; }
|
||||
sp<LayerBaseClient> getLayerUser(int32_t i) const;
|
||||
const Vector< wp<LayerBaseClient> >& getLayers() const { return mLayers; }
|
||||
const sp<IMemory>& controlBlockMemory() const { return mCblkMemory; }
|
||||
void dump(const char* what);
|
||||
const sp<SurfaceHeapManager>& getSurfaceHeapManager() const;
|
||||
|
||||
// pointer to this client's control block
|
||||
per_client_cblk_t* ctrlblk;
|
||||
@@ -95,15 +89,13 @@ public:
|
||||
private:
|
||||
int getClientPid() const { return mPid; }
|
||||
|
||||
int mPid;
|
||||
uint32_t mBitmap;
|
||||
SortedVector<uint8_t> mInUse;
|
||||
Vector<LayerBaseClient*> mLayers;
|
||||
sp<MemoryDealer> mCblkHeap;
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
sp<MemoryDealer> mSharedHeapAllocator;
|
||||
sp<MemoryDealer> mPMemAllocator;
|
||||
sp<IMemory> mCblkMemory;
|
||||
int mPid;
|
||||
uint32_t mBitmap;
|
||||
SortedVector<uint8_t> mInUse;
|
||||
Vector< wp<LayerBaseClient> > mLayers;
|
||||
sp<MemoryDealer> mCblkHeap;
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
sp<IMemory> mCblkMemory;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -126,6 +118,8 @@ public:
|
||||
|
||||
const DisplayHardware& displayHardware() const;
|
||||
const Transform& transform() const;
|
||||
EGLDisplay getEGLDisplay() const;
|
||||
|
||||
private:
|
||||
GraphicPlane(const GraphicPlane&);
|
||||
GraphicPlane operator = (const GraphicPlane&);
|
||||
@@ -169,28 +163,16 @@ public:
|
||||
virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags);
|
||||
virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
|
||||
virtual void signal() const;
|
||||
virtual status_t requestGPU(const sp<IGPUCallback>& callback,
|
||||
gpu_info_t* gpu);
|
||||
virtual status_t revokeGPU();
|
||||
|
||||
void screenReleased(DisplayID dpy);
|
||||
void screenAcquired(DisplayID dpy);
|
||||
|
||||
const sp<SurfaceHeapManager>& getSurfaceHeapManager() const {
|
||||
return mSurfaceHeapManager;
|
||||
}
|
||||
|
||||
const sp<GPUHardwareInterface>& getGPU() const {
|
||||
return mGPU;
|
||||
}
|
||||
|
||||
copybit_device_t* getBlitEngine() const;
|
||||
overlay_control_device_t* getOverlayEngine() const;
|
||||
|
||||
|
||||
status_t removeLayer(LayerBase* layer);
|
||||
status_t addLayer(LayerBase* layer);
|
||||
status_t invalidateLayerVisibility(LayerBase* layer);
|
||||
status_t removeLayer(const sp<LayerBase>& layer);
|
||||
status_t addLayer(const sp<LayerBase>& layer);
|
||||
status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
|
||||
|
||||
private:
|
||||
friend class BClient;
|
||||
@@ -205,20 +187,25 @@ private:
|
||||
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
|
||||
uint32_t flags);
|
||||
|
||||
LayerBaseClient* createNormalSurfaceLocked(Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
|
||||
sp<LayerBaseClient> createNormalSurfaceLocked(
|
||||
Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h,
|
||||
PixelFormat format, uint32_t flags);
|
||||
|
||||
LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display,
|
||||
sp<LayerBaseClient> createBlurSurfaceLocked(
|
||||
Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h, uint32_t flags);
|
||||
|
||||
LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display,
|
||||
sp<LayerBaseClient> createDimSurfaceLocked(
|
||||
Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h, uint32_t flags);
|
||||
|
||||
LayerBaseClient* createPushBuffersSurfaceLocked(Client* client, DisplayID display,
|
||||
sp<LayerBaseClient> createPushBuffersSurfaceLocked(
|
||||
Client* client, DisplayID display,
|
||||
int32_t id, uint32_t w, uint32_t h, uint32_t flags);
|
||||
|
||||
status_t destroySurface(SurfaceID surface_id);
|
||||
status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states);
|
||||
status_t destroySurface(SurfaceID surface_id);
|
||||
status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states);
|
||||
|
||||
|
||||
class LayerVector {
|
||||
@@ -226,15 +213,15 @@ private:
|
||||
inline LayerVector() { }
|
||||
LayerVector(const LayerVector&);
|
||||
inline size_t size() const { return layers.size(); }
|
||||
inline LayerBase*const* array() const { return layers.array(); }
|
||||
ssize_t add(LayerBase*, Vector<LayerBase*>::compar_t);
|
||||
ssize_t remove(LayerBase*);
|
||||
ssize_t reorder(LayerBase*, Vector<LayerBase*>::compar_t);
|
||||
ssize_t indexOf(LayerBase* key, size_t guess=0) const;
|
||||
inline LayerBase* operator [] (size_t i) const { return layers[i]; }
|
||||
inline sp<LayerBase> const* array() const { return layers.array(); }
|
||||
ssize_t add(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
|
||||
ssize_t remove(const sp<LayerBase>&);
|
||||
ssize_t reorder(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
|
||||
ssize_t indexOf(const sp<LayerBase>& key, size_t guess=0) const;
|
||||
inline sp<LayerBase> operator [] (size_t i) const { return layers[i]; }
|
||||
private:
|
||||
KeyedVector<LayerBase*, size_t> lookup;
|
||||
Vector<LayerBase*> layers;
|
||||
KeyedVector< sp<LayerBase> , size_t> lookup;
|
||||
Vector< sp<LayerBase> > layers;
|
||||
};
|
||||
|
||||
struct State {
|
||||
@@ -299,10 +286,9 @@ private:
|
||||
|
||||
|
||||
void destroyConnection(ClientID cid);
|
||||
LayerBaseClient* getLayerUser_l(SurfaceID index) const;
|
||||
status_t addLayer_l(LayerBase* layer);
|
||||
status_t removeLayer_l(LayerBase* layer);
|
||||
void destroy_all_removed_layers_l();
|
||||
sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const;
|
||||
status_t addLayer_l(const sp<LayerBase>& layer);
|
||||
status_t removeLayer_l(const sp<LayerBase>& layer);
|
||||
void free_resources_l();
|
||||
|
||||
uint32_t getTransactionFlags(uint32_t flags);
|
||||
@@ -335,17 +321,15 @@ private:
|
||||
// protected by mStateLock (but we could use another lock)
|
||||
Tokenizer mTokens;
|
||||
DefaultKeyedVector<ClientID, Client*> mClientsMap;
|
||||
DefaultKeyedVector<SurfaceID, LayerBaseClient*> mLayerMap;
|
||||
DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> > mLayerMap;
|
||||
GraphicPlane mGraphicPlanes[1];
|
||||
SortedVector<LayerBase*> mRemovedLayers;
|
||||
bool mLayersRemoved;
|
||||
Vector<Client*> mDisconnectedClients;
|
||||
|
||||
// constant members (no synchronization needed for access)
|
||||
sp<MemoryDealer> mServerHeap;
|
||||
sp<IMemory> mServerCblkMemory;
|
||||
surface_flinger_cblk_t* mServerCblk;
|
||||
sp<SurfaceHeapManager> mSurfaceHeapManager;
|
||||
sp<GPUHardwareInterface> mGPU;
|
||||
GLuint mWormholeTexName;
|
||||
sp<BootAnimation> mBootAnimation;
|
||||
nsecs_t mBootTime;
|
||||
|
||||
@@ -162,9 +162,10 @@ void Tokenizer::dump() const
|
||||
{
|
||||
const run_t* ranges = mRanges.array();
|
||||
const size_t c = mRanges.size();
|
||||
printf("Tokenizer (%p, size = %lu)\n", this, c);
|
||||
printf("Tokenizer (%p, size = %d)\n", this, int(c));
|
||||
for (size_t i=0 ; i<c ; i++) {
|
||||
printf("%lu: (%u, %u)\n", i, ranges[i].first, ranges[i].length);
|
||||
printf("%u: (%u, %u)\n", i,
|
||||
uint32_t(ranges[i].first), uint32_t(ranges[i].length));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
174
libs/surfaceflinger/purgatory/VRamHeap.cpp
Normal file
174
libs/surfaceflinger/purgatory/VRamHeap.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (C) 2008 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 <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <utils/MemoryDealer.h>
|
||||
#include <utils/MemoryBase.h>
|
||||
#include <utils/MemoryHeapPmem.h>
|
||||
#include <utils/MemoryHeapBase.h>
|
||||
|
||||
#include "GPUHardware/GPUHardware.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "VRamHeap.h"
|
||||
|
||||
#if HAVE_ANDROID_OS
|
||||
#include <linux/android_pmem.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Amount of memory we reserve for surface, per client in PMEM
|
||||
* (PMEM is used for 2D acceleration)
|
||||
* 8 MB of address space per client should be enough.
|
||||
*/
|
||||
static const int PMEM_SIZE = int(8 * 1024 * 1024);
|
||||
|
||||
int SurfaceHeapManager::global_pmem_heap = 0;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger,
|
||||
size_t clientHeapSize)
|
||||
: mFlinger(flinger), mClientHeapSize(clientHeapSize)
|
||||
{
|
||||
SurfaceHeapManager::global_pmem_heap = 1;
|
||||
}
|
||||
|
||||
SurfaceHeapManager::~SurfaceHeapManager()
|
||||
{
|
||||
}
|
||||
|
||||
void SurfaceHeapManager::onFirstRef()
|
||||
{
|
||||
if (global_pmem_heap) {
|
||||
const char* device = "/dev/pmem";
|
||||
mPMemHeap = new PMemHeap(device, PMEM_SIZE);
|
||||
if (mPMemHeap->base() == MAP_FAILED) {
|
||||
mPMemHeap.clear();
|
||||
global_pmem_heap = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sp<MemoryDealer> SurfaceHeapManager::createHeap(
|
||||
uint32_t flags,
|
||||
pid_t client_pid,
|
||||
const sp<MemoryDealer>& defaultAllocator)
|
||||
{
|
||||
sp<MemoryDealer> dealer;
|
||||
|
||||
if (flags & ISurfaceComposer::eGPU) {
|
||||
// don't grant GPU memory if GPU is disabled
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
property_get("debug.egl.hw", value, "1");
|
||||
if (atoi(value) == 0) {
|
||||
flags &= ~ISurfaceComposer::eGPU;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & ISurfaceComposer::eGPU) {
|
||||
// FIXME: this is msm7201A specific, where gpu surfaces may not be secure
|
||||
if (!(flags & ISurfaceComposer::eSecure)) {
|
||||
// if GPU doesn't work, we try eHardware
|
||||
flags |= ISurfaceComposer::eHardware;
|
||||
// asked for GPU memory, try that first
|
||||
dealer = mFlinger->getGPU()->request(client_pid);
|
||||
}
|
||||
}
|
||||
|
||||
if (dealer == NULL) {
|
||||
if (defaultAllocator != NULL)
|
||||
// if a default allocator is given, use that
|
||||
dealer = defaultAllocator;
|
||||
}
|
||||
|
||||
if (dealer == NULL) {
|
||||
// always try h/w accelerated memory first
|
||||
if (global_pmem_heap) {
|
||||
const sp<PMemHeap>& heap(mPMemHeap);
|
||||
if (dealer == NULL && heap != NULL) {
|
||||
dealer = new MemoryDealer(
|
||||
heap->createClientHeap(),
|
||||
heap->getAllocator());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dealer == NULL) {
|
||||
// return the ashmem allocator (software rendering)
|
||||
dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap");
|
||||
}
|
||||
return dealer;
|
||||
}
|
||||
|
||||
sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
sp<SimpleBestFitAllocator> allocator;
|
||||
|
||||
// this is only used for debugging
|
||||
switch (type) {
|
||||
case NATIVE_MEMORY_TYPE_PMEM:
|
||||
if (mPMemHeap != 0) {
|
||||
allocator = mPMemHeap->getAllocator();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return allocator;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved)
|
||||
: MemoryHeapBase(device, size)
|
||||
{
|
||||
//LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
|
||||
if (base() != MAP_FAILED) {
|
||||
//LOGD("%s, %u bytes", device, virtualSize());
|
||||
if (reserved == 0)
|
||||
reserved = virtualSize();
|
||||
mAllocator = new SimpleBestFitAllocator(reserved);
|
||||
}
|
||||
}
|
||||
|
||||
PMemHeap::~PMemHeap() {
|
||||
//LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
|
||||
}
|
||||
|
||||
sp<MemoryHeapPmem> PMemHeap::createClientHeap() {
|
||||
sp<MemoryHeapBase> parentHeap(this);
|
||||
return new MemoryHeapPmem(parentHeap);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
78
libs/surfaceflinger/purgatory/VRamHeap.h
Normal file
78
libs/surfaceflinger/purgatory/VRamHeap.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2008 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_VRAM_HEAP_H
|
||||
#define ANDROID_VRAM_HEAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/MemoryDealer.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class PMemHeap;
|
||||
class MemoryHeapPmem;
|
||||
class SurfaceFlinger;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class SurfaceHeapManager : public RefBase
|
||||
{
|
||||
public:
|
||||
SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize);
|
||||
virtual ~SurfaceHeapManager();
|
||||
virtual void onFirstRef();
|
||||
/* use ISurfaceComposer flags eGPU|eHArdware|eSecure */
|
||||
sp<MemoryDealer> createHeap(uint32_t flags=0, pid_t client_pid = 0,
|
||||
const sp<MemoryDealer>& defaultAllocator = 0);
|
||||
|
||||
// used for debugging only...
|
||||
sp<SimpleBestFitAllocator> getAllocator(int type) const;
|
||||
|
||||
private:
|
||||
sp<PMemHeap> getHeap(int type) const;
|
||||
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
mutable Mutex mLock;
|
||||
size_t mClientHeapSize;
|
||||
sp<PMemHeap> mPMemHeap;
|
||||
static int global_pmem_heap;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class PMemHeap : public MemoryHeapBase
|
||||
{
|
||||
public:
|
||||
PMemHeap(const char* const vram,
|
||||
size_t size=0, size_t reserved=0);
|
||||
virtual ~PMemHeap();
|
||||
|
||||
virtual const sp<SimpleBestFitAllocator>& getAllocator() const {
|
||||
return mAllocator;
|
||||
}
|
||||
virtual sp<MemoryHeapPmem> createClientHeap();
|
||||
|
||||
private:
|
||||
sp<SimpleBestFitAllocator> mAllocator;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_VRAM_HEAP_H
|
||||
16
libs/surfaceflinger/tests/resize/Android.mk
Normal file
16
libs/surfaceflinger/tests/resize/Android.mk
Normal file
@@ -0,0 +1,16 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
resize.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
libutils \
|
||||
libui
|
||||
|
||||
LOCAL_MODULE:= test-resize
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
60
libs/surfaceflinger/tests/resize/resize.cpp
Normal file
60
libs/surfaceflinger/tests/resize/resize.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <cutils/memory.h>
|
||||
|
||||
#include <utils/IPCThreadState.h>
|
||||
#include <utils/ProcessState.h>
|
||||
#include <utils/IServiceManager.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <ui/Surface.h>
|
||||
#include <ui/ISurface.h>
|
||||
#include <ui/Overlay.h>
|
||||
#include <ui/SurfaceComposerClient.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
namespace android {
|
||||
class Test {
|
||||
public:
|
||||
static const sp<ISurface>& getISurface(const sp<Surface>& s) {
|
||||
return s->getISurface();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// set up the thread-pool
|
||||
sp<ProcessState> proc(ProcessState::self());
|
||||
ProcessState::self()->startThreadPool();
|
||||
|
||||
// create a client to surfaceflinger
|
||||
sp<SurfaceComposerClient> client = new SurfaceComposerClient();
|
||||
|
||||
// create pushbuffer surface
|
||||
sp<Surface> surface = client->createSurface(getpid(), 0, 160, 240,
|
||||
PIXEL_FORMAT_RGB_565);
|
||||
|
||||
|
||||
client->openTransaction();
|
||||
surface->setLayer(100000);
|
||||
client->closeTransaction();
|
||||
|
||||
Surface::SurfaceInfo info;
|
||||
surface->lock(&info);
|
||||
ssize_t bpr = info.s * bytesPerPixel(info.format);
|
||||
android_memset16((uint16_t*)info.bits, 0xF800, bpr*info.h);
|
||||
surface->unlockAndPost();
|
||||
|
||||
surface->lock(&info);
|
||||
android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h);
|
||||
surface->unlockAndPost();
|
||||
|
||||
client->openTransaction();
|
||||
surface->setSize(320, 240);
|
||||
client->closeTransaction();
|
||||
|
||||
|
||||
IPCThreadState::self()->joinThreadPool();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2,9 +2,9 @@ LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
BufferMapper.cpp \
|
||||
Camera.cpp \
|
||||
CameraParameters.cpp \
|
||||
EGLDisplaySurface.cpp \
|
||||
EGLNativeWindowSurface.cpp \
|
||||
EventHub.cpp \
|
||||
EventRecurrence.cpp \
|
||||
|
||||
83
libs/ui/BufferMapper.cpp
Normal file
83
libs/ui/BufferMapper.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "BufferMapper"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <ui/BufferMapper.h>
|
||||
#include <ui/Rect.h>
|
||||
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
BufferMapper::BufferMapper()
|
||||
: mAllocMod(0)
|
||||
{
|
||||
hw_module_t const* module;
|
||||
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
|
||||
LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
|
||||
if (err == 0) {
|
||||
mAllocMod = (gralloc_module_t const *)module;
|
||||
}
|
||||
}
|
||||
|
||||
status_t BufferMapper::map(buffer_handle_t handle, void** addr)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
status_t err = mAllocMod->map(mAllocMod, handle, addr);
|
||||
LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t BufferMapper::unmap(buffer_handle_t handle)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
status_t err = mAllocMod->unmap(mAllocMod, handle);
|
||||
LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t BufferMapper::lock(buffer_handle_t handle, int usage, const Rect& bounds)
|
||||
{
|
||||
status_t err = mAllocMod->lock(mAllocMod, handle, usage,
|
||||
bounds.left, bounds.top, bounds.width(), bounds.height());
|
||||
LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t BufferMapper::unlock(buffer_handle_t handle)
|
||||
{
|
||||
status_t err = mAllocMod->unlock(mAllocMod, handle);
|
||||
LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
@@ -1,519 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** Copyright 2007 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "EGLDisplaySurface"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/atomic.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <hardware/copybit.h>
|
||||
|
||||
#include <ui/SurfaceComposerClient.h>
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <ui/Region.h>
|
||||
#include <ui/EGLDisplaySurface.h>
|
||||
|
||||
#if HAVE_ANDROID_OS
|
||||
#include <linux/msm_mdp.h>
|
||||
#endif
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <pixelflinger/format.h>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
egl_native_window_t* android_createDisplaySurface()
|
||||
{
|
||||
egl_native_window_t* s = new android::EGLDisplaySurface();
|
||||
s->memory_type = NATIVE_MEMORY_TYPE_GPU;
|
||||
return s;
|
||||
}
|
||||
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
EGLDisplaySurface::EGLDisplaySurface()
|
||||
: EGLNativeSurface<EGLDisplaySurface>()
|
||||
{
|
||||
egl_native_window_t::version = sizeof(egl_native_window_t);
|
||||
egl_native_window_t::ident = 0;
|
||||
egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef;
|
||||
egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef;
|
||||
egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers;
|
||||
egl_native_window_t::connect = 0;
|
||||
egl_native_window_t::disconnect = 0;
|
||||
|
||||
mFb[0].data = 0;
|
||||
mFb[1].data = 0;
|
||||
mBlitEngine = 0;
|
||||
egl_native_window_t::fd = mapFrameBuffer();
|
||||
if (egl_native_window_t::fd >= 0) {
|
||||
|
||||
hw_module_t const* module;
|
||||
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
|
||||
copybit_open(module, &mBlitEngine);
|
||||
}
|
||||
|
||||
const float in2mm = 25.4f;
|
||||
float refreshRate = 1000000000000000LLU / (
|
||||
float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres )
|
||||
* ( mInfo.left_margin + mInfo.right_margin + mInfo.xres )
|
||||
* mInfo.pixclock);
|
||||
|
||||
const GGLSurface& buffer = mFb[1 - mIndex];
|
||||
egl_native_window_t::width = buffer.width;
|
||||
egl_native_window_t::height = buffer.height;
|
||||
egl_native_window_t::stride = buffer.stride;
|
||||
egl_native_window_t::format = buffer.format;
|
||||
egl_native_window_t::base = intptr_t(mFb[0].data);
|
||||
egl_native_window_t::offset =
|
||||
intptr_t(buffer.data) - egl_native_window_t::base;
|
||||
egl_native_window_t::flags = 0;
|
||||
egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width;
|
||||
egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height;
|
||||
egl_native_window_t::fps = refreshRate;
|
||||
egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB;
|
||||
// no error, set the magic word
|
||||
egl_native_window_t::magic = 0x600913;
|
||||
}
|
||||
mSwapCount = -1;
|
||||
mPageFlipCount = 0;
|
||||
}
|
||||
|
||||
EGLDisplaySurface::~EGLDisplaySurface()
|
||||
{
|
||||
magic = 0;
|
||||
copybit_close(mBlitEngine);
|
||||
mBlitEngine = 0;
|
||||
close(egl_native_window_t::fd);
|
||||
munmap(mFb[0].data, mSize);
|
||||
if (!(mFlags & PAGE_FLIP))
|
||||
free((void*)mFb[1].data);
|
||||
}
|
||||
|
||||
void EGLDisplaySurface::hook_incRef(NativeWindowType window) {
|
||||
EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
|
||||
that->incStrong(that);
|
||||
}
|
||||
void EGLDisplaySurface::hook_decRef(NativeWindowType window) {
|
||||
EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
|
||||
that->decStrong(that);
|
||||
}
|
||||
uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) {
|
||||
EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
|
||||
return that->swapBuffers();
|
||||
}
|
||||
|
||||
void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h)
|
||||
{
|
||||
mInfo.reserved[0] = 0x54445055; // "UPDT";
|
||||
mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
|
||||
mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
|
||||
}
|
||||
|
||||
uint32_t EGLDisplaySurface::swapBuffers()
|
||||
{
|
||||
#define SHOW_FPS 0
|
||||
#if SHOW_FPS
|
||||
nsecs_t now = systemTime();
|
||||
if (mSwapCount == -1) {
|
||||
mTime = now;
|
||||
mSwapCount = 0;
|
||||
mSleep = 0;
|
||||
} else {
|
||||
nsecs_t d = now-mTime;
|
||||
if (d >= seconds(1)) {
|
||||
double fps = (mSwapCount * double(seconds(1))) / double(d);
|
||||
LOGD("%f fps, sleep=%d / frame",
|
||||
fps, (int)ns2us(mSleep / mSwapCount));
|
||||
mSwapCount = 0;
|
||||
mTime = now;
|
||||
mSleep = 0;
|
||||
} else {
|
||||
mSwapCount++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* If we can't do the page_flip, just copy the back buffer to the front */
|
||||
if (!(mFlags & PAGE_FLIP)) {
|
||||
memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// do the actual flip
|
||||
mIndex = 1 - mIndex;
|
||||
mInfo.activate = FB_ACTIVATE_VBL;
|
||||
mInfo.yoffset = mIndex ? mInfo.yres : 0;
|
||||
if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) {
|
||||
LOGE("FBIOPUT_VSCREENINFO failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* this is a monstrous hack: Because the h/w accelerator is not able
|
||||
* to render directly into the framebuffer, we need to copy its
|
||||
* internal framebuffer out to the fb.
|
||||
* oem[0] is used to access the fd of internal fb.
|
||||
* All this is needed only in standalone mode, in SurfaceFlinger mode
|
||||
* we control where the GPU renders.
|
||||
* We do this only if we have copybit, since this hack is needed only
|
||||
* with msm7k.
|
||||
*/
|
||||
if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0] && mBlitEngine) {
|
||||
copybit_device_t *copybit = mBlitEngine;
|
||||
copybit_rect_t sdrect = { 0, 0,
|
||||
egl_native_window_t::width, egl_native_window_t::height };
|
||||
copybit_image_t dst = {
|
||||
egl_native_window_t::width,
|
||||
egl_native_window_t::height,
|
||||
egl_native_window_t::format,
|
||||
egl_native_window_t::offset,
|
||||
(void*)egl_native_window_t::base,
|
||||
egl_native_window_t::fd
|
||||
};
|
||||
copybit_image_t src = {
|
||||
egl_native_window_t::width,
|
||||
egl_native_window_t::height,
|
||||
egl_native_window_t::format, // XXX: use proper format
|
||||
egl_native_window_t::offset,
|
||||
(void*)egl_native_window_t::base, // XXX: use proper base
|
||||
egl_native_window_t::oem[0]
|
||||
};
|
||||
region_iterator it(Region(Rect(
|
||||
egl_native_window_t::width, egl_native_window_t::height)));
|
||||
copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
|
||||
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
|
||||
copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
|
||||
copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it);
|
||||
}
|
||||
|
||||
// update the address of the buffer to draw to next
|
||||
const GGLSurface& buffer = mFb[1 - mIndex];
|
||||
egl_native_window_t::offset =
|
||||
intptr_t(buffer.data) - egl_native_window_t::base;
|
||||
|
||||
#if SHOW_FPS
|
||||
mSleep += systemTime()-now;
|
||||
#endif
|
||||
|
||||
mPageFlipCount++;
|
||||
|
||||
// We don't support screen-size changes for now
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t EGLDisplaySurface::getPageFlipCount() const
|
||||
{
|
||||
return mPageFlipCount;
|
||||
}
|
||||
|
||||
void EGLDisplaySurface::copyFrontToBack(const Region& copyback)
|
||||
{
|
||||
#if HAVE_ANDROID_OS
|
||||
if (mBlitEngine) {
|
||||
copybit_image_t dst = {
|
||||
w: egl_native_window_t::stride,
|
||||
h: egl_native_window_t::height,
|
||||
format: egl_native_window_t::format,
|
||||
offset: mFb[1-mIndex].data - mFb[0].data,
|
||||
base: (void*)egl_native_window_t::base,
|
||||
fd: egl_native_window_t::fd
|
||||
};
|
||||
copybit_image_t src = {
|
||||
w: egl_native_window_t::stride,
|
||||
h: egl_native_window_t::height,
|
||||
format: egl_native_window_t::format,
|
||||
offset: mFb[mIndex].data - mFb[0].data,
|
||||
base: (void*)egl_native_window_t::base,
|
||||
fd: egl_native_window_t::fd
|
||||
};
|
||||
region_iterator it(copyback);
|
||||
mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* no extra copy needed since we copied back to front instead of
|
||||
* flipping */
|
||||
if (!(mFlags & PAGE_FLIP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Region::iterator iterator(copyback);
|
||||
if (iterator) {
|
||||
Rect r;
|
||||
uint8_t* const screen_src = mFb[ mIndex].data;
|
||||
uint8_t* const screen_dst = mFb[1-mIndex].data;
|
||||
const size_t bpp = bytesPerPixel(egl_native_window_t::format);
|
||||
const size_t bpr = egl_native_window_t::stride * bpp;
|
||||
while (iterator.iterate(&r)) {
|
||||
ssize_t h = r.bottom - r.top;
|
||||
if (h) {
|
||||
size_t size = (r.right - r.left) * bpp;
|
||||
size_t o = (r.left + egl_native_window_t::stride * r.top) * bpp;
|
||||
uint8_t* s = screen_src + o;
|
||||
uint8_t* d = screen_dst + o;
|
||||
if (size == bpr) {
|
||||
size *= h;
|
||||
h = 1;
|
||||
}
|
||||
do {
|
||||
memcpy(d, s, size);
|
||||
d += bpr;
|
||||
s += bpr;
|
||||
} while (--h > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst)
|
||||
{
|
||||
#if HAVE_ANDROID_OS
|
||||
if (mBlitEngine) {
|
||||
copybit_image_t src = {
|
||||
w: egl_native_window_t::stride,
|
||||
h: egl_native_window_t::height,
|
||||
format: egl_native_window_t::format,
|
||||
offset: mFb[mIndex].data - mFb[0].data,
|
||||
base: (void*)egl_native_window_t::base,
|
||||
fd: egl_native_window_t::fd
|
||||
};
|
||||
region_iterator it(Region(Rect(
|
||||
egl_native_window_t::width, egl_native_window_t::height)));
|
||||
mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint8_t* const screen_src = mFb[ mIndex].data;
|
||||
const size_t bpp = bytesPerPixel(egl_native_window_t::format);
|
||||
const size_t bpr = egl_native_window_t::stride * bpp;
|
||||
memcpy((char*)dst.base + dst.offset, screen_src,
|
||||
bpr*egl_native_window_t::height);
|
||||
}
|
||||
}
|
||||
|
||||
void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst)
|
||||
{
|
||||
#if HAVE_ANDROID_OS
|
||||
if (mBlitEngine) {
|
||||
copybit_image_t src = {
|
||||
w: egl_native_window_t::stride,
|
||||
h: egl_native_window_t::height,
|
||||
format: egl_native_window_t::format,
|
||||
offset: mFb[1-mIndex].data - mFb[0].data,
|
||||
base: (void*)egl_native_window_t::base,
|
||||
fd: egl_native_window_t::fd
|
||||
};
|
||||
region_iterator it(Region(Rect(
|
||||
egl_native_window_t::width, egl_native_window_t::height)));
|
||||
mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
uint8_t* const screen_src = mFb[1-mIndex].data;
|
||||
const size_t bpp = bytesPerPixel(egl_native_window_t::format);
|
||||
const size_t bpr = egl_native_window_t::stride * bpp;
|
||||
memcpy((char*)dst.base + dst.offset, screen_src,
|
||||
bpr*egl_native_window_t::height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t EGLDisplaySurface::mapFrameBuffer()
|
||||
{
|
||||
char const * const device_template[] = {
|
||||
"/dev/graphics/fb%u",
|
||||
"/dev/fb%u",
|
||||
0 };
|
||||
int fd = -1;
|
||||
int i=0;
|
||||
char name[64];
|
||||
while ((fd==-1) && device_template[i]) {
|
||||
snprintf(name, 64, device_template[i], 0);
|
||||
fd = open(name, O_RDWR, 0);
|
||||
i++;
|
||||
}
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
struct fb_fix_screeninfo finfo;
|
||||
if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
|
||||
return -errno;
|
||||
|
||||
struct fb_var_screeninfo info;
|
||||
if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
|
||||
return -errno;
|
||||
|
||||
info.reserved[0] = 0;
|
||||
info.reserved[1] = 0;
|
||||
info.reserved[2] = 0;
|
||||
info.xoffset = 0;
|
||||
info.yoffset = 0;
|
||||
info.yres_virtual = info.yres * 2;
|
||||
info.bits_per_pixel = 16;
|
||||
/* Explicitly request 5/6/5 */
|
||||
info.red.offset = 11;
|
||||
info.red.length = 5;
|
||||
info.green.offset = 5;
|
||||
info.green.length = 6;
|
||||
info.blue.offset = 0;
|
||||
info.blue.length = 5;
|
||||
info.transp.offset = 0;
|
||||
info.transp.length = 0;
|
||||
info.activate = FB_ACTIVATE_NOW;
|
||||
|
||||
uint32_t flags = PAGE_FLIP;
|
||||
if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
|
||||
info.yres_virtual = info.yres;
|
||||
flags &= ~PAGE_FLIP;
|
||||
LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
|
||||
}
|
||||
|
||||
if (info.yres_virtual < info.yres * 2) {
|
||||
info.yres_virtual = info.yres;
|
||||
flags &= ~PAGE_FLIP;
|
||||
LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
|
||||
info.yres_virtual, info.yres*2);
|
||||
}
|
||||
|
||||
if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
|
||||
return -errno;
|
||||
|
||||
int refreshRate = 1000000000000000LLU /
|
||||
(
|
||||
uint64_t( info.upper_margin + info.lower_margin + info.yres )
|
||||
* ( info.left_margin + info.right_margin + info.xres )
|
||||
* info.pixclock
|
||||
);
|
||||
|
||||
if (refreshRate == 0) {
|
||||
// bleagh, bad info from the driver
|
||||
refreshRate = 60*1000; // 60 Hz
|
||||
}
|
||||
if (int(info.width) <= 0 || int(info.height) <= 0) {
|
||||
// the driver doesn't return that information
|
||||
// default to 160 dpi
|
||||
info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
|
||||
info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
|
||||
}
|
||||
|
||||
float xdpi = (info.xres * 25.4f) / info.width;
|
||||
float ydpi = (info.yres * 25.4f) / info.height;
|
||||
float fps = refreshRate / 1000.0f;
|
||||
|
||||
LOGI( "using (fd=%d)\n"
|
||||
"id = %s\n"
|
||||
"xres = %d px\n"
|
||||
"yres = %d px\n"
|
||||
"xres_virtual = %d px\n"
|
||||
"yres_virtual = %d px\n"
|
||||
"bpp = %d\n"
|
||||
"r = %2u:%u\n"
|
||||
"g = %2u:%u\n"
|
||||
"b = %2u:%u\n",
|
||||
fd,
|
||||
finfo.id,
|
||||
info.xres,
|
||||
info.yres,
|
||||
info.xres_virtual,
|
||||
info.yres_virtual,
|
||||
info.bits_per_pixel,
|
||||
info.red.offset, info.red.length,
|
||||
info.green.offset, info.green.length,
|
||||
info.blue.offset, info.blue.length
|
||||
);
|
||||
|
||||
LOGI( "width = %d mm (%f dpi)\n"
|
||||
"height = %d mm (%f dpi)\n"
|
||||
"refresh rate = %.2f Hz\n",
|
||||
info.width, xdpi,
|
||||
info.height, ydpi,
|
||||
fps
|
||||
);
|
||||
|
||||
|
||||
if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
|
||||
return -errno;
|
||||
|
||||
if (finfo.smem_len <= 0)
|
||||
return -errno;
|
||||
|
||||
/*
|
||||
* Open and map the display.
|
||||
*/
|
||||
|
||||
void* buffer = (uint16_t*) mmap(
|
||||
0, finfo.smem_len,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fd, 0);
|
||||
|
||||
if (buffer == MAP_FAILED)
|
||||
return -errno;
|
||||
|
||||
// at least for now, always clear the fb
|
||||
memset(buffer, 0, finfo.smem_len);
|
||||
|
||||
uint8_t* offscreen[2];
|
||||
offscreen[0] = (uint8_t*)buffer;
|
||||
if (flags & PAGE_FLIP) {
|
||||
offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres;
|
||||
} else {
|
||||
offscreen[1] = (uint8_t*)malloc(finfo.smem_len);
|
||||
if (offscreen[1] == 0) {
|
||||
munmap(buffer, finfo.smem_len);
|
||||
return NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
mFlags = flags;
|
||||
mInfo = info;
|
||||
mFinfo = finfo;
|
||||
mSize = finfo.smem_len;
|
||||
mIndex = 0;
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
mFb[i].version = sizeof(GGLSurface);
|
||||
mFb[i].width = info.xres;
|
||||
mFb[i].height = info.yres;
|
||||
mFb[i].stride = finfo.line_length / (info.bits_per_pixel >> 3);
|
||||
mFb[i].data = (GGLubyte*)(offscreen[i]);
|
||||
mFb[i].format = GGL_PIXEL_FORMAT_RGB_565;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -20,142 +20,225 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/atomic.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include <ui/SurfaceComposerClient.h>
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <pixelflinger/format.h>
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface)
|
||||
: EGLNativeSurface<EGLNativeWindowSurface>(),
|
||||
mSurface(surface), mConnected(false)
|
||||
{
|
||||
egl_native_window_t::magic = 0x600913;
|
||||
egl_native_window_t::version = sizeof(egl_native_window_t);
|
||||
egl_native_window_t::ident = 0;
|
||||
egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef;
|
||||
egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef;
|
||||
egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers;
|
||||
egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect;
|
||||
egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect;
|
||||
|
||||
DisplayInfo dinfo;
|
||||
SurfaceComposerClient::getDisplayInfo(0, &dinfo);
|
||||
egl_native_window_t::xdpi = dinfo.xdpi;
|
||||
egl_native_window_t::ydpi = dinfo.ydpi;
|
||||
egl_native_window_t::fps = dinfo.fps;
|
||||
egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER;
|
||||
}
|
||||
/*
|
||||
* This implements the (main) framebuffer management. This class is used
|
||||
* mostly by SurfaceFlinger, but also by command line GL application.
|
||||
*
|
||||
* In fact this is an implementation of android_native_window_t on top of
|
||||
* the framebuffer.
|
||||
*
|
||||
* Currently it is pretty simple, it manages only two buffers (the front and
|
||||
* back buffer).
|
||||
*
|
||||
*/
|
||||
|
||||
EGLNativeWindowSurface::~EGLNativeWindowSurface()
|
||||
FramebufferNativeWindow::FramebufferNativeWindow()
|
||||
: BASE(), fbDev(0), grDev(0)
|
||||
{
|
||||
disconnect();
|
||||
mSurface.clear();
|
||||
magic = 0;
|
||||
}
|
||||
hw_module_t const* module;
|
||||
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
|
||||
int stride;
|
||||
framebuffer_open(module, &fbDev);
|
||||
gralloc_open(module, &grDev);
|
||||
int err;
|
||||
|
||||
void EGLNativeWindowSurface::hook_incRef(NativeWindowType window)
|
||||
{
|
||||
EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
|
||||
that->incStrong(that);
|
||||
}
|
||||
|
||||
// initialize the buffer FIFO
|
||||
mNumBuffers = 2;
|
||||
mNumFreeBuffers = 2;
|
||||
mBufferHead = mNumBuffers-1;
|
||||
buffers[0] = new NativeBuffer(
|
||||
fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
|
||||
buffers[1] = new NativeBuffer(
|
||||
fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
|
||||
|
||||
err = grDev->alloc(grDev,
|
||||
fbDev->width, fbDev->height, fbDev->format,
|
||||
GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
|
||||
|
||||
void EGLNativeWindowSurface::hook_decRef(NativeWindowType window)
|
||||
{
|
||||
EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
|
||||
that->decStrong(that);
|
||||
}
|
||||
LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
|
||||
fbDev->width, fbDev->height, strerror(-err));
|
||||
|
||||
void EGLNativeWindowSurface::hook_connect(NativeWindowType window)
|
||||
{
|
||||
EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
|
||||
that->connect();
|
||||
}
|
||||
err = grDev->alloc(grDev,
|
||||
fbDev->width, fbDev->height, fbDev->format,
|
||||
GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
|
||||
|
||||
void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window)
|
||||
{
|
||||
EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
|
||||
that->disconnect();
|
||||
}
|
||||
LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
|
||||
fbDev->width, fbDev->height, strerror(-err));
|
||||
|
||||
uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window)
|
||||
{
|
||||
EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
|
||||
return that->swapBuffers();
|
||||
}
|
||||
gralloc_module_t* m =
|
||||
reinterpret_cast<gralloc_module_t*>(grDev->common.module);
|
||||
|
||||
void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h)
|
||||
{
|
||||
mSurface->setSwapRectangle(Rect(l, t, l+w, t+h));
|
||||
}
|
||||
|
||||
uint32_t EGLNativeWindowSurface::swapBuffers()
|
||||
{
|
||||
const int w = egl_native_window_t::width;
|
||||
const int h = egl_native_window_t::height;
|
||||
const sp<Surface>& surface(mSurface);
|
||||
Surface::SurfaceInfo info;
|
||||
surface->unlockAndPost();
|
||||
surface->lock(&info);
|
||||
// update the address of the buffer to draw to next
|
||||
egl_native_window_t::base = intptr_t(info.base);
|
||||
egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
|
||||
|
||||
// update size if it changed
|
||||
if (w != int(info.w) || h != int(info.h)) {
|
||||
egl_native_window_t::width = info.w;
|
||||
egl_native_window_t::height = info.h;
|
||||
egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
|
||||
egl_native_window_t::format = info.format;
|
||||
return EGL_NATIVES_FLAG_SIZE_CHANGED;
|
||||
// FIXME: do we actually need to map the framebuffer?
|
||||
m->map(m, buffers[0]->handle, &buffers[0]->bits);
|
||||
m->map(m, buffers[1]->handle, &buffers[1]->bits);
|
||||
}
|
||||
|
||||
uint32_t flags = fbDev->flags & SURFACE_FLAG_MAPPED;
|
||||
|
||||
/*
|
||||
* FIXME: SURFACE_FLAG_PRESERVE_CONTENT
|
||||
* how to implement this, there is no concept of preserve content in
|
||||
* the framebuffer, which just "posts" buffer.
|
||||
*
|
||||
* It looks like what we need is a way to know if the posted buffer can
|
||||
* be reused. But if so, why allocating 2 buffers?...
|
||||
*
|
||||
* should the lock/unlock calls take care of the copy-back?
|
||||
*
|
||||
*
|
||||
* In the end, the client wants to know if the backbuffer is preserved
|
||||
* though... it's complicated.
|
||||
*
|
||||
*/
|
||||
|
||||
//flags |= SURFACE_FLAG_PRESERVE_CONTENT;
|
||||
|
||||
|
||||
const_cast<uint32_t&>(android_native_window_t::flags) = flags;
|
||||
const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
|
||||
const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi;
|
||||
const_cast<int&>(android_native_window_t::minSwapInterval) =
|
||||
fbDev->minSwapInterval;
|
||||
const_cast<int&>(android_native_window_t::maxSwapInterval) =
|
||||
fbDev->maxSwapInterval;
|
||||
|
||||
android_native_window_t::connect = connect;
|
||||
android_native_window_t::disconnect = disconnect;
|
||||
android_native_window_t::setSwapInterval = setSwapInterval;
|
||||
android_native_window_t::setSwapRectangle = setSwapRectangle;
|
||||
android_native_window_t::dequeueBuffer = dequeueBuffer;
|
||||
android_native_window_t::lockBuffer = lockBuffer;
|
||||
android_native_window_t::queueBuffer = queueBuffer;
|
||||
}
|
||||
|
||||
FramebufferNativeWindow::~FramebufferNativeWindow() {
|
||||
grDev->free(grDev, buffers[0]->handle);
|
||||
grDev->free(grDev, buffers[1]->handle);
|
||||
gralloc_module_t* m =
|
||||
reinterpret_cast<gralloc_module_t*>(grDev->common.module);
|
||||
m->unmap(m, buffers[0]->handle);
|
||||
m->unmap(m, buffers[1]->handle);
|
||||
gralloc_close(grDev);
|
||||
framebuffer_close(fbDev);
|
||||
}
|
||||
|
||||
void FramebufferNativeWindow::connect(android_native_window_t* window)
|
||||
{
|
||||
}
|
||||
|
||||
void FramebufferNativeWindow::disconnect(android_native_window_t* window)
|
||||
{
|
||||
}
|
||||
|
||||
int FramebufferNativeWindow::setSwapInterval(
|
||||
android_native_window_t* window, int interval)
|
||||
{
|
||||
framebuffer_device_t* fb = getSelf(window)->fbDev;
|
||||
return fb->setSwapInterval(fb, interval);
|
||||
}
|
||||
|
||||
int FramebufferNativeWindow::setSwapRectangle(android_native_window_t* window,
|
||||
int l, int t, int w, int h)
|
||||
{
|
||||
FramebufferNativeWindow* self = getSelf(window);
|
||||
Mutex::Autolock _l(self->mutex);
|
||||
self->mDirty = Rect(l, t, l+w, t+h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EGLNativeWindowSurface::connect()
|
||||
{
|
||||
if (!mConnected) {
|
||||
Surface::SurfaceInfo info;
|
||||
mSurface->lock(&info);
|
||||
mSurface->setSwapRectangle(Rect(info.w, info.h));
|
||||
mConnected = true;
|
||||
int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window,
|
||||
android_native_buffer_t** buffer)
|
||||
{
|
||||
FramebufferNativeWindow* self = getSelf(window);
|
||||
Mutex::Autolock _l(self->mutex);
|
||||
framebuffer_device_t* fb = self->fbDev;
|
||||
|
||||
egl_native_window_t::width = info.w;
|
||||
egl_native_window_t::height = info.h;
|
||||
egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
|
||||
egl_native_window_t::format = info.format;
|
||||
egl_native_window_t::base = intptr_t(info.base);
|
||||
egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
|
||||
// FIXME: egl_native_window_t::memory_type used to be set from
|
||||
// mSurface, but we wanted to break this dependency. We set it to
|
||||
// GPU because the software rendered doesn't care, but the h/w
|
||||
// accelerator needs it. Eventually, this value should go away
|
||||
// completely, since memory will be managed by OpenGL.
|
||||
egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU;
|
||||
egl_native_window_t::fd = 0;
|
||||
// wait for a free buffer
|
||||
while (!self->mNumFreeBuffers) {
|
||||
self->mCondition.wait(self->mutex);
|
||||
}
|
||||
// get this buffer
|
||||
self->mNumFreeBuffers--;
|
||||
int index = self->mBufferHead++;
|
||||
if (self->mBufferHead >= self->mNumBuffers)
|
||||
self->mBufferHead = 0;
|
||||
|
||||
*buffer = self->buffers[index].get();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EGLNativeWindowSurface::disconnect()
|
||||
int FramebufferNativeWindow::lockBuffer(android_native_window_t* window,
|
||||
android_native_buffer_t* buffer)
|
||||
{
|
||||
if (mConnected) {
|
||||
mSurface->unlock();
|
||||
mConnected = false;
|
||||
FramebufferNativeWindow* self = getSelf(window);
|
||||
Mutex::Autolock _l(self->mutex);
|
||||
|
||||
// wait that the buffer we're locking is not front anymore
|
||||
while (self->front == buffer) {
|
||||
self->mCondition.wait(self->mutex);
|
||||
}
|
||||
|
||||
gralloc_module_t* m =
|
||||
reinterpret_cast<gralloc_module_t*>(self->grDev->common.module);
|
||||
const Rect& dirty(self->mDirty);
|
||||
|
||||
buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
|
||||
int res = m->lock(m, handle, GRALLOC_USAGE_HW_FB,
|
||||
dirty.left, dirty.right, dirty.width(), dirty.height());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int FramebufferNativeWindow::queueBuffer(android_native_window_t* window,
|
||||
android_native_buffer_t* buffer)
|
||||
{
|
||||
FramebufferNativeWindow* self = getSelf(window);
|
||||
Mutex::Autolock _l(self->mutex);
|
||||
framebuffer_device_t* fb = self->fbDev;
|
||||
gralloc_module_t* m =
|
||||
reinterpret_cast<gralloc_module_t*>(self->grDev->common.module);
|
||||
|
||||
buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
|
||||
m->unlock(m, handle);
|
||||
int res = fb->post(fb, handle);
|
||||
|
||||
self->front = static_cast<NativeBuffer*>(buffer);
|
||||
self->mNumFreeBuffers++;
|
||||
self->mCondition.broadcast();
|
||||
return res;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
EGLNativeWindowType android_createDisplaySurface(void)
|
||||
{
|
||||
return new android::FramebufferNativeWindow();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "ISurface"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
@@ -23,10 +25,13 @@
|
||||
|
||||
#include <ui/ISurface.h>
|
||||
#include <ui/Overlay.h>
|
||||
#include <ui/Surface.h>
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
ISurface::BufferHeap::BufferHeap()
|
||||
: w(0), h(0), hor_stride(0), ver_stride(0), format(0),
|
||||
transform(0), flags(0)
|
||||
@@ -55,6 +60,8 @@ ISurface::BufferHeap::~BufferHeap()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
class BpSurface : public BpInterface<ISurface>
|
||||
{
|
||||
public:
|
||||
@@ -63,6 +70,15 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual sp<SurfaceBuffer> getBuffer()
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
|
||||
remote()->transact(GET_BUFFER, data, &reply);
|
||||
sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
virtual status_t registerBuffers(const BufferHeap& buffers)
|
||||
{
|
||||
Parcel data, reply;
|
||||
@@ -122,6 +138,11 @@ status_t BnSurface::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
switch(code) {
|
||||
case GET_BUFFER: {
|
||||
CHECK_INTERFACE(ISurface, data, reply);
|
||||
sp<SurfaceBuffer> buffer(getBuffer());
|
||||
return SurfaceBuffer::writeToParcel(reply, buffer.get());
|
||||
}
|
||||
case REGISTER_BUFFERS: {
|
||||
CHECK_INTERFACE(ISurface, data, reply);
|
||||
BufferHeap buffer;
|
||||
|
||||
@@ -114,36 +114,6 @@ public:
|
||||
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
|
||||
}
|
||||
|
||||
virtual status_t requestGPU(
|
||||
const sp<IGPUCallback>& callback, gpu_info_t* gpu)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||
data.writeStrongBinder(callback->asBinder());
|
||||
remote()->transact(BnSurfaceComposer::REQUEST_GPU, data, &reply);
|
||||
gpu->regs = interface_cast<IMemory>(reply.readStrongBinder());
|
||||
gpu->count = reply.readInt32();
|
||||
|
||||
// FIXME: for now, we don't dynamically allocate the regions array
|
||||
size_t maxCount = sizeof(gpu->regions)/sizeof(*gpu->regions);
|
||||
if (gpu->count > maxCount)
|
||||
return BAD_VALUE;
|
||||
|
||||
for (size_t i=0 ; i<gpu->count ; i++) {
|
||||
gpu->regions[i].region = interface_cast<IMemory>(reply.readStrongBinder());
|
||||
gpu->regions[i].reserved = reply.readInt32();
|
||||
}
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
virtual status_t revokeGPU()
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||
remote()->transact(BnSurfaceComposer::REVOKE_GPU, data, &reply);
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
virtual void signal() const
|
||||
{
|
||||
Parcel data, reply;
|
||||
@@ -201,9 +171,6 @@ status_t BnSurfaceComposer::onTransact(
|
||||
case BOOT_FINISHED: {
|
||||
bootFinished();
|
||||
} break;
|
||||
case REVOKE_GPU: {
|
||||
reply->writeInt32( revokeGPU() );
|
||||
} break;
|
||||
case SIGNAL: {
|
||||
signal();
|
||||
} break;
|
||||
@@ -211,26 +178,6 @@ status_t BnSurfaceComposer::onTransact(
|
||||
sp<IBinder> b = getCblk()->asBinder();
|
||||
reply->writeStrongBinder(b);
|
||||
} break;
|
||||
case REQUEST_GPU: {
|
||||
// TODO: this should be protected by a permission
|
||||
gpu_info_t info;
|
||||
sp<IGPUCallback> callback
|
||||
= interface_cast<IGPUCallback>(data.readStrongBinder());
|
||||
status_t res = requestGPU(callback, &info);
|
||||
|
||||
// FIXME: for now, we don't dynamically allocate the regions array
|
||||
size_t maxCount = sizeof(info.regions)/sizeof(*info.regions);
|
||||
if (info.count > maxCount)
|
||||
return BAD_VALUE;
|
||||
|
||||
reply->writeStrongBinder(info.regs->asBinder());
|
||||
reply->writeInt32(info.count);
|
||||
for (size_t i=0 ; i<info.count ; i++) {
|
||||
reply->writeStrongBinder(info.regions[i].region->asBinder());
|
||||
reply->writeInt32(info.regions[i].reserved);
|
||||
}
|
||||
reply->writeInt32(res);
|
||||
} break;
|
||||
default:
|
||||
return UNKNOWN_TRANSACTION;
|
||||
}
|
||||
@@ -239,41 +186,4 @@ status_t BnSurfaceComposer::onTransact(
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
enum {
|
||||
// Note: BOOT_FINISHED must remain this value, it is called by ActivityManagerService.
|
||||
GPU_LOST = IBinder::FIRST_CALL_TRANSACTION
|
||||
};
|
||||
|
||||
class BpGPUCallback : public BpInterface<IGPUCallback>
|
||||
{
|
||||
public:
|
||||
BpGPUCallback(const sp<IBinder>& impl)
|
||||
: BpInterface<IGPUCallback>(impl)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void gpuLost()
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(IGPUCallback::getInterfaceDescriptor());
|
||||
remote()->transact(GPU_LOST, data, &reply, IBinder::FLAG_ONEWAY);
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_META_INTERFACE(GPUCallback, "android.ui.IGPUCallback");
|
||||
|
||||
status_t BnGPUCallback::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
switch(code) {
|
||||
case GPU_LOST: {
|
||||
CHECK_INTERFACE(IGPUCallback, data, reply);
|
||||
gpuLost();
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
default:
|
||||
return BBinder::onTransact(code, data, reply, flags);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -191,8 +191,6 @@ status_t ISurfaceFlingerClient::surface_data_t::readFromParcel(const Parcel& par
|
||||
{
|
||||
token = parcel.readInt32();
|
||||
identity = parcel.readInt32();
|
||||
heap[0] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
|
||||
heap[1] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -200,8 +198,6 @@ status_t ISurfaceFlingerClient::surface_data_t::writeToParcel(Parcel* parcel) co
|
||||
{
|
||||
parcel->writeInt32(token);
|
||||
parcel->writeInt32(identity);
|
||||
parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL);
|
||||
parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,12 +129,8 @@ OverlayRef::OverlayRef(overlay_handle_t handle, const sp<IOverlay>& channel,
|
||||
OverlayRef::~OverlayRef()
|
||||
{
|
||||
if (mOwnHandle) {
|
||||
/* FIXME: handles should be promoted to "real" API and be handled by
|
||||
* the framework */
|
||||
for (int i=0 ; i<mOverlayHandle->numFds ; i++) {
|
||||
close(mOverlayHandle->data[i]);
|
||||
}
|
||||
free((void*)mOverlayHandle);
|
||||
native_handle_close(mOverlayHandle);
|
||||
native_handle_delete(const_cast<native_handle*>(mOverlayHandle));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +143,7 @@ sp<OverlayRef> OverlayRef::readFromParcel(const Parcel& data) {
|
||||
uint32_t f = data.readInt32();
|
||||
uint32_t ws = data.readInt32();
|
||||
uint32_t hs = data.readInt32();
|
||||
native_handle* handle = data.readNativeHandle(NULL, NULL);
|
||||
native_handle* handle = data.readNativeHandle();
|
||||
|
||||
result = new OverlayRef();
|
||||
result->mOverlayHandle = handle;
|
||||
@@ -169,7 +165,7 @@ status_t OverlayRef::writeToParcel(Parcel* reply, const sp<OverlayRef>& o) {
|
||||
reply->writeInt32(o->mFormat);
|
||||
reply->writeInt32(o->mWidthStride);
|
||||
reply->writeInt32(o->mHeightStride);
|
||||
reply->writeNativeHandle(*(o->mOverlayHandle));
|
||||
reply->writeNativeHandle(o->mOverlayHandle);
|
||||
} else {
|
||||
reply->writeStrongBinder(NULL);
|
||||
}
|
||||
|
||||
@@ -23,24 +23,126 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <utils/Atomic.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/IPCThreadState.h>
|
||||
#include <utils/IMemory.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/BufferMapper.h>
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
#include <ui/ISurface.h>
|
||||
#include <ui/Surface.h>
|
||||
#include <ui/SurfaceComposerClient.h>
|
||||
#include <ui/Rect.h>
|
||||
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
#include <private/ui/SharedState.h>
|
||||
#include <private/ui/LayerState.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ============================================================================
|
||||
// SurfaceBuffer
|
||||
// ============================================================================
|
||||
|
||||
SurfaceBuffer::SurfaceBuffer()
|
||||
: BASE(), handle(0), mOwner(false)
|
||||
{
|
||||
width =
|
||||
height =
|
||||
stride =
|
||||
format =
|
||||
usage = 0;
|
||||
android_native_buffer_t::getHandle = getHandle;
|
||||
}
|
||||
|
||||
SurfaceBuffer::SurfaceBuffer(const Parcel& data)
|
||||
: BASE(), handle(0), mOwner(true)
|
||||
{
|
||||
// we own the handle in this case
|
||||
width = data.readInt32();
|
||||
height = data.readInt32();
|
||||
stride = data.readInt32();
|
||||
format = data.readInt32();
|
||||
usage = data.readInt32();
|
||||
handle = data.readNativeHandle();
|
||||
android_native_buffer_t::getHandle = getHandle;
|
||||
}
|
||||
|
||||
SurfaceBuffer::~SurfaceBuffer()
|
||||
{
|
||||
if (handle && mOwner) {
|
||||
native_handle_close(handle);
|
||||
native_handle_delete(const_cast<native_handle*>(handle));
|
||||
}
|
||||
}
|
||||
|
||||
int SurfaceBuffer::getHandle(android_native_buffer_t const * base,
|
||||
buffer_handle_t* handle)
|
||||
{
|
||||
*handle = getSelf(base)->handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t SurfaceBuffer::writeToParcel(Parcel* reply,
|
||||
android_native_buffer_t const* buffer)
|
||||
{
|
||||
buffer_handle_t handle;
|
||||
status_t err = buffer->getHandle(buffer, &handle);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
reply->writeInt32(buffer->width);
|
||||
reply->writeInt32(buffer->height);
|
||||
reply->writeInt32(buffer->stride);
|
||||
reply->writeInt32(buffer->format);
|
||||
reply->writeInt32(buffer->usage);
|
||||
reply->writeNativeHandle(handle);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
static void copyBlt(const android_native_buffer_t* dst,
|
||||
const android_native_buffer_t* src, const Region& reg)
|
||||
{
|
||||
Region::iterator iterator(reg);
|
||||
if (iterator) {
|
||||
// NOTE: dst and src must be the same format
|
||||
Rect r;
|
||||
const size_t bpp = bytesPerPixel(src->format);
|
||||
const size_t dbpr = dst->stride * bpp;
|
||||
const size_t sbpr = src->stride * bpp;
|
||||
while (iterator.iterate(&r)) {
|
||||
ssize_t h = r.bottom - r.top;
|
||||
if (h) {
|
||||
size_t size = (r.right - r.left) * bpp;
|
||||
uint8_t* s = (GGLubyte*)src->bits +
|
||||
(r.left + src->stride * r.top) * bpp;
|
||||
uint8_t* d = (GGLubyte*)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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Surface
|
||||
// ============================================================================
|
||||
|
||||
Surface::Surface(const sp<SurfaceComposerClient>& client,
|
||||
const sp<ISurface>& surface,
|
||||
@@ -51,26 +153,44 @@ Surface::Surface(const sp<SurfaceComposerClient>& client,
|
||||
mToken(data.token), mIdentity(data.identity),
|
||||
mFormat(format), mFlags(flags), mOwner(owner)
|
||||
{
|
||||
android_native_window_t::connect = connect;
|
||||
android_native_window_t::disconnect = disconnect;
|
||||
android_native_window_t::setSwapInterval = setSwapInterval;
|
||||
android_native_window_t::setSwapRectangle = setSwapRectangle;
|
||||
android_native_window_t::dequeueBuffer = dequeueBuffer;
|
||||
android_native_window_t::lockBuffer = lockBuffer;
|
||||
android_native_window_t::queueBuffer = queueBuffer;
|
||||
|
||||
mSwapRectangle.makeInvalid();
|
||||
mSurfaceHeapBase[0] = 0;
|
||||
mSurfaceHeapBase[1] = 0;
|
||||
mHeap[0] = data.heap[0];
|
||||
mHeap[1] = data.heap[1];
|
||||
|
||||
DisplayInfo dinfo;
|
||||
SurfaceComposerClient::getDisplayInfo(0, &dinfo);
|
||||
const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
|
||||
const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
|
||||
// FIXME: set real values here
|
||||
const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
|
||||
const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
|
||||
const_cast<uint32_t&>(android_native_window_t::flags) = 0;
|
||||
}
|
||||
|
||||
Surface::Surface(Surface const* rhs)
|
||||
: mOwner(false)
|
||||
{
|
||||
mToken = rhs->mToken;
|
||||
mIdentity= rhs->mIdentity;
|
||||
mClient = rhs->mClient;
|
||||
mSurface = rhs->mSurface;
|
||||
mHeap[0] = rhs->mHeap[0];
|
||||
mHeap[1] = rhs->mHeap[1];
|
||||
mFormat = rhs->mFormat;
|
||||
mFlags = rhs->mFlags;
|
||||
mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0];
|
||||
mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1];
|
||||
// FIXME: we really should get rid of this ctor. the memcpy below
|
||||
//should be safe for now, but android_native_window_t is not supposed
|
||||
// to be clonable.
|
||||
memcpy( static_cast<android_native_window_t*>(this),
|
||||
static_cast<android_native_window_t const *>(rhs),
|
||||
sizeof(android_native_window_t));
|
||||
|
||||
mToken = rhs->mToken;
|
||||
mIdentity = rhs->mIdentity;
|
||||
mClient = rhs->mClient;
|
||||
mSurface = rhs->mSurface;
|
||||
mBuffers[0] = rhs->mBuffers[0];
|
||||
mBuffers[1] = rhs->mBuffers[1];
|
||||
mFormat = rhs->mFormat;
|
||||
mFlags = rhs->mFlags;
|
||||
mSwapRectangle.makeInvalid();
|
||||
}
|
||||
|
||||
@@ -78,21 +198,26 @@ Surface::~Surface()
|
||||
{
|
||||
if (mOwner && mToken>=0 && mClient!=0) {
|
||||
mClient->destroySurface(mToken);
|
||||
if (mBuffers[0] != 0) {
|
||||
BufferMapper::get().unmap(mBuffers[0]->getHandle());
|
||||
}
|
||||
if (mBuffers[1] != 0) {
|
||||
BufferMapper::get().unmap(mBuffers[1]->getHandle());
|
||||
}
|
||||
}
|
||||
mClient.clear();
|
||||
mSurface.clear();
|
||||
mHeap[0].clear();
|
||||
mHeap[1].clear();
|
||||
IPCThreadState::self()->flushCommands();
|
||||
}
|
||||
|
||||
sp<Surface> Surface::dup() const
|
||||
{
|
||||
// FIXME: we should get rid of Surface::dup()
|
||||
Surface const * r = this;
|
||||
if (this && mOwner) {
|
||||
// the only reason we need to do this is because of Java's garbage
|
||||
// collector: because we're creating a copy of the Surface
|
||||
// instead of a reference, we can garantee that when our last
|
||||
// instead of a reference, we can guarantee that when our last
|
||||
// reference goes away, the real surface will be deleted.
|
||||
// Without this hack (the code is correct too), we'd have to
|
||||
// wait for a GC for the surface to go away.
|
||||
@@ -101,31 +226,244 @@ sp<Surface> Surface::dup() const
|
||||
return const_cast<Surface*>(r);
|
||||
}
|
||||
|
||||
status_t Surface::nextBuffer(SurfaceInfo* info) {
|
||||
return mClient->nextBuffer(this, info);
|
||||
status_t Surface::validate(per_client_cblk_t const* cblk) const
|
||||
{
|
||||
if (cblk == 0) {
|
||||
LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
|
||||
return NO_INIT;
|
||||
}
|
||||
status_t err = cblk->validate(mToken);
|
||||
if (err != NO_ERROR) {
|
||||
LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
|
||||
mToken, mIdentity, err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
|
||||
LOGE("using an invalid surface id=%d, identity=%u should be %d",
|
||||
mToken, mIdentity, cblk->layers[mToken].identity);
|
||||
return NO_INIT;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int Surface::setSwapRectangle(android_native_window_t* window,
|
||||
int l, int t, int w, int h)
|
||||
{
|
||||
Surface* self = getSelf(window);
|
||||
self->setSwapRectangle(Rect(l, t, l+w, t+h));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Surface::connect(android_native_window_t* window)
|
||||
{
|
||||
}
|
||||
|
||||
void Surface::disconnect(android_native_window_t* window)
|
||||
{
|
||||
}
|
||||
|
||||
int Surface::setSwapInterval(android_native_window_t* window, int interval)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Surface::dequeueBuffer(android_native_window_t* window,
|
||||
android_native_buffer_t** buffer)
|
||||
{
|
||||
Surface* self = getSelf(window);
|
||||
return self->dequeueBuffer(buffer);
|
||||
}
|
||||
|
||||
int Surface::lockBuffer(android_native_window_t* window,
|
||||
android_native_buffer_t* buffer)
|
||||
{
|
||||
Surface* self = getSelf(window);
|
||||
return self->lockBuffer(buffer);
|
||||
}
|
||||
|
||||
int Surface::queueBuffer(android_native_window_t* window,
|
||||
android_native_buffer_t* buffer)
|
||||
{
|
||||
Surface* self = getSelf(window);
|
||||
return self->queueBuffer(buffer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int Surface::dequeueBuffer(android_native_buffer_t** buffer)
|
||||
{
|
||||
// FIXME: dequeueBuffer() needs proper implementation
|
||||
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
|
||||
per_client_cblk_t* const cblk = mClient->mControl;
|
||||
status_t err = validate(cblk);
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
SurfaceID index(mToken);
|
||||
|
||||
int32_t backIdx = cblk->lock_layer(size_t(index),
|
||||
per_client_cblk_t::BLOCKING);
|
||||
|
||||
if (backIdx < 0)
|
||||
return status_t(backIdx);
|
||||
|
||||
mBackbufferIndex = backIdx;
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[index]);
|
||||
|
||||
volatile const surface_info_t* const back = lcblk->surface + backIdx;
|
||||
if (back->flags & surface_info_t::eNeedNewBuffer) {
|
||||
getBufferLocked(backIdx);
|
||||
}
|
||||
|
||||
const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
|
||||
*buffer = backBuffer.get();
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int Surface::lockBuffer(android_native_buffer_t* buffer)
|
||||
{
|
||||
// FIXME: lockBuffer() needs proper implementation
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Surface::queueBuffer(android_native_buffer_t* buffer)
|
||||
{
|
||||
Mutex::Autolock _l(mSurfaceLock);
|
||||
|
||||
per_client_cblk_t* const cblk = mClient->mControl;
|
||||
status_t err = validate(cblk);
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
// transmit the dirty region
|
||||
const Region dirty(swapRectangle());
|
||||
SurfaceID index(mToken);
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[index]);
|
||||
_send_dirty_region(lcblk, dirty);
|
||||
|
||||
uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
|
||||
if (!(newstate & eNextFlipPending))
|
||||
mClient->signalServer();
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
status_t Surface::lock(SurfaceInfo* info, bool blocking) {
|
||||
return Surface::lock(info, NULL, blocking);
|
||||
}
|
||||
|
||||
status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) {
|
||||
if (heapBase(0) == 0) return INVALID_OPERATION;
|
||||
if (heapBase(1) == 0) return INVALID_OPERATION;
|
||||
return mClient->lockSurface(this, info, dirty, blocking);
|
||||
status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
|
||||
{
|
||||
// FIXME: needs some locking here
|
||||
android_native_buffer_t* backBuffer;
|
||||
status_t err = dequeueBuffer(&backBuffer);
|
||||
if (err == NO_ERROR) {
|
||||
err = lockBuffer(backBuffer);
|
||||
if (err == NO_ERROR) {
|
||||
backBuffer->common.incRef(&backBuffer->common);
|
||||
mLockedBuffer = backBuffer;
|
||||
other->w = backBuffer->width;
|
||||
other->h = backBuffer->height;
|
||||
other->s = backBuffer->stride;
|
||||
other->usage = backBuffer->usage;
|
||||
other->format = backBuffer->format;
|
||||
other->bits = backBuffer->bits;
|
||||
|
||||
// we handle copy-back here...
|
||||
|
||||
const Rect bounds(backBuffer->width, backBuffer->height);
|
||||
Region newDirtyRegion;
|
||||
|
||||
per_client_cblk_t* const cblk = mClient->mControl;
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
|
||||
volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
|
||||
if (back->flags & surface_info_t::eBufferDirty) {
|
||||
// content is meaningless in this case and the whole surface
|
||||
// needs to be redrawn.
|
||||
newDirtyRegion.set(bounds);
|
||||
if (dirty) {
|
||||
*dirty = newDirtyRegion;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (dirty) {
|
||||
dirty->andSelf(Region(bounds));
|
||||
newDirtyRegion = *dirty;
|
||||
} else {
|
||||
newDirtyRegion.set(bounds);
|
||||
}
|
||||
Region copyback;
|
||||
if (!(lcblk->flags & eNoCopyBack)) {
|
||||
const Region previousDirtyRegion(dirtyRegion());
|
||||
copyback = previousDirtyRegion.subtract(newDirtyRegion);
|
||||
}
|
||||
const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
|
||||
if (!copyback.isEmpty() && frontBuffer!=0) {
|
||||
// copy front to back
|
||||
copyBlt(backBuffer, frontBuffer.get(), copyback);
|
||||
}
|
||||
}
|
||||
setDirtyRegion(newDirtyRegion);
|
||||
|
||||
|
||||
Rect lockBounds(backBuffer->width, backBuffer->height);
|
||||
if (dirty) {
|
||||
lockBounds = dirty->bounds();
|
||||
}
|
||||
buffer_handle_t handle;
|
||||
backBuffer->getHandle(backBuffer, &handle);
|
||||
status_t res = BufferMapper::get().lock(handle,
|
||||
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
|
||||
lockBounds);
|
||||
LOGW_IF(res, "failed locking buffer %d (%p)",
|
||||
mBackbufferIndex, handle);
|
||||
setSwapRectangle(lockBounds);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t Surface::unlockAndPost()
|
||||
{
|
||||
// FIXME: needs some locking here
|
||||
|
||||
if (mLockedBuffer == 0)
|
||||
return BAD_VALUE;
|
||||
|
||||
buffer_handle_t handle;
|
||||
mLockedBuffer->getHandle(mLockedBuffer, &handle);
|
||||
status_t res = BufferMapper::get().unlock(handle);
|
||||
LOGW_IF(res, "failed unlocking buffer %d (%p)",
|
||||
mBackbufferIndex, handle);
|
||||
|
||||
const Rect dirty(dirtyRegion().bounds());
|
||||
setSwapRectangle(dirty);
|
||||
status_t err = queueBuffer(mLockedBuffer);
|
||||
mLockedBuffer->common.decRef(&mLockedBuffer->common);
|
||||
mLockedBuffer = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t Surface::unlockAndPost() {
|
||||
if (heapBase(0) == 0) return INVALID_OPERATION;
|
||||
if (heapBase(1) == 0) return INVALID_OPERATION;
|
||||
return mClient->unlockAndPostSurface(this);
|
||||
void Surface::_send_dirty_region(
|
||||
layer_cblk_t* lcblk, const Region& dirty)
|
||||
{
|
||||
const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
|
||||
flat_region_t* flat_region = lcblk->region + index;
|
||||
status_t err = dirty.write(flat_region, sizeof(flat_region_t));
|
||||
if (err < NO_ERROR) {
|
||||
// region doesn't fit, use the bounds
|
||||
const Region reg(dirty.bounds());
|
||||
reg.write(flat_region, sizeof(flat_region_t));
|
||||
}
|
||||
}
|
||||
|
||||
status_t Surface::unlock() {
|
||||
if (heapBase(0) == 0) return INVALID_OPERATION;
|
||||
if (heapBase(1) == 0) return INVALID_OPERATION;
|
||||
return mClient->unlockSurface(this);
|
||||
}
|
||||
|
||||
status_t Surface::setLayer(int32_t layer) {
|
||||
return mClient->setLayer(this, layer);
|
||||
@@ -183,8 +521,6 @@ sp<Surface> Surface::readFromParcel(Parcel* parcel)
|
||||
ISurfaceFlingerClient::surface_data_t data;
|
||||
sp<IBinder> clientBinder= parcel->readStrongBinder();
|
||||
sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder());
|
||||
data.heap[0] = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
|
||||
data.heap[1] = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
|
||||
data.token = parcel->readInt32();
|
||||
data.identity = parcel->readInt32();
|
||||
PixelFormat format = parcel->readInt32();
|
||||
@@ -204,21 +540,16 @@ status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel)
|
||||
uint32_t identity = 0;
|
||||
sp<SurfaceComposerClient> client;
|
||||
sp<ISurface> sur;
|
||||
sp<IMemoryHeap> heap[2];
|
||||
if (surface->isValid()) {
|
||||
token = surface->mToken;
|
||||
identity = surface->mIdentity;
|
||||
client = surface->mClient;
|
||||
sur = surface->mSurface;
|
||||
heap[0] = surface->mHeap[0];
|
||||
heap[1] = surface->mHeap[1];
|
||||
format = surface->mFormat;
|
||||
flags = surface->mFlags;
|
||||
}
|
||||
parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
|
||||
parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
|
||||
parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL);
|
||||
parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL);
|
||||
parcel->writeInt32(token);
|
||||
parcel->writeInt32(identity);
|
||||
parcel->writeInt32(format);
|
||||
@@ -233,23 +564,24 @@ bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs)
|
||||
return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
|
||||
}
|
||||
|
||||
void* Surface::heapBase(int i) const
|
||||
status_t Surface::getBufferLocked(int index)
|
||||
{
|
||||
void* heapBase = mSurfaceHeapBase[i];
|
||||
// map lazily so it doesn't get mapped in clients that don't need it
|
||||
if (heapBase == 0) {
|
||||
const sp<IMemoryHeap>& heap(mHeap[i]);
|
||||
if (heap != 0) {
|
||||
heapBase = static_cast<uint8_t*>(heap->base());
|
||||
if (heapBase == MAP_FAILED) {
|
||||
heapBase = NULL;
|
||||
LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)",
|
||||
heap->asBinder().get(), heap.get());
|
||||
}
|
||||
mSurfaceHeapBase[i] = heapBase;
|
||||
status_t err = NO_MEMORY;
|
||||
sp<SurfaceBuffer> buffer = mSurface->getBuffer();
|
||||
LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
|
||||
if (buffer != 0) {
|
||||
sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
|
||||
if (currentBuffer != 0) {
|
||||
BufferMapper::get().unmap(currentBuffer->getHandle());
|
||||
currentBuffer.clear();
|
||||
}
|
||||
err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits);
|
||||
LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
|
||||
if (err == NO_ERROR) {
|
||||
currentBuffer = buffer;
|
||||
}
|
||||
}
|
||||
return heapBase;
|
||||
return err;
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -29,27 +29,21 @@
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/IPCThreadState.h>
|
||||
#include <utils/IServiceManager.h>
|
||||
#include <utils/IMemory.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/ISurfaceComposer.h>
|
||||
#include <ui/ISurfaceFlingerClient.h>
|
||||
#include <ui/ISurface.h>
|
||||
#include <ui/SurfaceComposerClient.h>
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <ui/Point.h>
|
||||
|
||||
#include <private/ui/SharedState.h>
|
||||
#include <private/ui/LayerState.h>
|
||||
#include <private/ui/SurfaceFlingerSynchro.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include <utils/BpBinder.h>
|
||||
|
||||
#define VERBOSE(...) ((void)0)
|
||||
//#define VERBOSE LOGD
|
||||
|
||||
@@ -109,50 +103,8 @@ static volatile surface_flinger_cblk_t const * get_cblk()
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void copyBlt(const GGLSurface& dst,
|
||||
const GGLSurface& src, const Region& reg)
|
||||
{
|
||||
Region::iterator iterator(reg);
|
||||
if (iterator) {
|
||||
// NOTE: dst and src must be the same format
|
||||
Rect r;
|
||||
const size_t bpp = bytesPerPixel(src.format);
|
||||
const size_t dbpr = dst.stride * bpp;
|
||||
const size_t sbpr = src.stride * bpp;
|
||||
while (iterator.iterate(&r)) {
|
||||
ssize_t h = r.bottom - r.top;
|
||||
if (h) {
|
||||
size_t size = (r.right - r.left) * bpp;
|
||||
uint8_t* s = src.data + (r.left + src.stride * r.top) * bpp;
|
||||
uint8_t* d = dst.data + (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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
surface_flinger_cblk_t::surface_flinger_cblk_t()
|
||||
{
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
per_client_cblk_t::per_client_cblk_t()
|
||||
{
|
||||
}
|
||||
|
||||
// these functions are used by the clients
|
||||
inline status_t per_client_cblk_t::validate(size_t i) const {
|
||||
status_t per_client_cblk_t::validate(size_t i) const {
|
||||
if (uint32_t(i) >= NUM_LAYERS_MAX)
|
||||
return BAD_INDEX;
|
||||
if (layers[i].swapState & eInvalidSurface)
|
||||
@@ -248,8 +200,9 @@ int32_t per_client_cblk_t::lock_layer(size_t i, uint32_t flags)
|
||||
index = (state&eIndex) ^ ((state&eFlipRequested)>>1);
|
||||
|
||||
// make sure this buffer is valid
|
||||
if (layer->surface[index].bits_offset < 0) {
|
||||
return status_t(layer->surface[index].bits_offset);
|
||||
status_t err = layer->surface[index].status;
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (inspect) {
|
||||
@@ -273,7 +226,7 @@ done:
|
||||
|
||||
uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
|
||||
{
|
||||
// atomically set eFlipRequested and clear eLocked and optionnaly
|
||||
// atomically set eFlipRequested and clear eLocked and optionally
|
||||
// set eNextFlipPending if eFlipRequested was already set
|
||||
|
||||
layer_cblk_t * const layer = layers + i;
|
||||
@@ -290,7 +243,7 @@ uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
|
||||
|
||||
if (oldvalue & eFlipRequested)
|
||||
newvalue |= eNextFlipPending;
|
||||
// if eFlipRequested was alread set, set eNextFlipPending
|
||||
// if eFlipRequested was already set, set eNextFlipPending
|
||||
|
||||
} while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState)));
|
||||
|
||||
@@ -298,9 +251,9 @@ uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
|
||||
int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift),
|
||||
int(newvalue));
|
||||
|
||||
// from this point, the server can kick in at anytime and use the first
|
||||
// from this point, the server can kick in at any time and use the first
|
||||
// buffer, so we cannot use it anymore, and we must use the 'other'
|
||||
// buffer instead (or wait if it is not availlable yet, see lock_layer).
|
||||
// buffer instead (or wait if it is not available yet, see lock_layer).
|
||||
|
||||
return newvalue;
|
||||
}
|
||||
@@ -376,32 +329,6 @@ status_t SurfaceComposerClient::initCheck() const
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
status_t SurfaceComposerClient::validateSurface(
|
||||
per_client_cblk_t const* cblk, Surface const * surface)
|
||||
{
|
||||
SurfaceID index = surface->ID();
|
||||
if (cblk == 0) {
|
||||
LOGE("cblk is null (surface id=%d, identity=%u)",
|
||||
index, surface->getIdentity());
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
status_t err = cblk->validate(index);
|
||||
if (err != NO_ERROR) {
|
||||
LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
|
||||
index, surface->getIdentity(), err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) {
|
||||
LOGE("using an invalid surface id=%d, identity=%u should be %d",
|
||||
index, surface->getIdentity(), cblk->layers[index].identity);
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
sp<IBinder> SurfaceComposerClient::connection() const
|
||||
{
|
||||
return (mClient != 0) ? mClient->asBinder() : 0;
|
||||
@@ -439,7 +366,6 @@ void SurfaceComposerClient::dispose()
|
||||
|
||||
sp<IMemory> controlMemory;
|
||||
sp<ISurfaceFlingerClient> client;
|
||||
sp<IMemoryHeap> surfaceHeap;
|
||||
|
||||
{
|
||||
Mutex::Autolock _lg(gLock);
|
||||
@@ -462,9 +388,7 @@ void SurfaceComposerClient::dispose()
|
||||
delete mPrebuiltLayerState;
|
||||
mPrebuiltLayerState = 0;
|
||||
controlMemory = mControlMemory;
|
||||
surfaceHeap = mSurfaceHeap;
|
||||
mControlMemory.clear();
|
||||
mSurfaceHeap.clear();
|
||||
mControl = 0;
|
||||
mStatus = NO_INIT;
|
||||
}
|
||||
@@ -528,6 +452,12 @@ ssize_t SurfaceComposerClient::getNumberOfDisplays()
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void SurfaceComposerClient::signalServer()
|
||||
{
|
||||
mSignalServer->signal();
|
||||
}
|
||||
|
||||
sp<Surface> SurfaceComposerClient::createSurface(
|
||||
int pid,
|
||||
DisplayID display,
|
||||
@@ -568,186 +498,6 @@ status_t SurfaceComposerClient::destroySurface(SurfaceID sid)
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t SurfaceComposerClient::nextBuffer(Surface* surface,
|
||||
Surface::SurfaceInfo* info)
|
||||
{
|
||||
SurfaceID index = surface->ID();
|
||||
per_client_cblk_t* const cblk = mControl;
|
||||
status_t err = validateSurface(cblk, surface);
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
int32_t backIdx = surface->mBackbufferIndex;
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[index]);
|
||||
const surface_info_t* const front = lcblk->surface + (1-backIdx);
|
||||
info->w = front->w;
|
||||
info->h = front->h;
|
||||
info->format = front->format;
|
||||
info->base = surface->heapBase(1-backIdx);
|
||||
info->bits = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset);
|
||||
info->bpr = front->bpr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t SurfaceComposerClient::lockSurface(
|
||||
Surface* surface,
|
||||
Surface::SurfaceInfo* other,
|
||||
Region* dirty,
|
||||
bool blocking)
|
||||
{
|
||||
Mutex::Autolock _l(surface->getLock());
|
||||
|
||||
SurfaceID index = surface->ID();
|
||||
per_client_cblk_t* const cblk = mControl;
|
||||
status_t err = validateSurface(cblk, surface);
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
int32_t backIdx = cblk->lock_layer(size_t(index),
|
||||
per_client_cblk_t::BLOCKING);
|
||||
if (backIdx >= 0) {
|
||||
surface->mBackbufferIndex = backIdx;
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[index]);
|
||||
const surface_info_t* const back = lcblk->surface + backIdx;
|
||||
const surface_info_t* const front = lcblk->surface + (1-backIdx);
|
||||
other->w = back->w;
|
||||
other->h = back->h;
|
||||
other->format = back->format;
|
||||
other->base = surface->heapBase(backIdx);
|
||||
other->bits = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset);
|
||||
other->bpr = back->bpr;
|
||||
|
||||
const Rect bounds(other->w, other->h);
|
||||
Region newDirtyRegion;
|
||||
|
||||
if (back->flags & surface_info_t::eBufferDirty) {
|
||||
/* it is safe to write *back here, because we're guaranteed
|
||||
* SurfaceFlinger is not touching it (since it just granted
|
||||
* access to us) */
|
||||
const_cast<surface_info_t*>(back)->flags &=
|
||||
~surface_info_t::eBufferDirty;
|
||||
|
||||
// content is meaningless in this case and the whole surface
|
||||
// needs to be redrawn.
|
||||
|
||||
newDirtyRegion.set(bounds);
|
||||
if (dirty) {
|
||||
*dirty = newDirtyRegion;
|
||||
}
|
||||
|
||||
//if (bytesPerPixel(other->format) == 4) {
|
||||
// android_memset32(
|
||||
// (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr);
|
||||
//} else {
|
||||
// android_memset16( // fill with green
|
||||
// (uint16_t*)other->bits, 0x7E0, other->h * other->bpr);
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dirty) {
|
||||
dirty->andSelf(Region(bounds));
|
||||
newDirtyRegion = *dirty;
|
||||
} else {
|
||||
newDirtyRegion.set(bounds);
|
||||
}
|
||||
|
||||
Region copyback;
|
||||
if (!(lcblk->flags & eNoCopyBack)) {
|
||||
const Region previousDirtyRegion(surface->dirtyRegion());
|
||||
copyback = previousDirtyRegion.subtract(newDirtyRegion);
|
||||
}
|
||||
|
||||
if (!copyback.isEmpty()) {
|
||||
// copy front to back
|
||||
GGLSurface cb;
|
||||
cb.version = sizeof(GGLSurface);
|
||||
cb.width = back->w;
|
||||
cb.height = back->h;
|
||||
cb.stride = back->stride;
|
||||
cb.data = (GGLubyte*)surface->heapBase(backIdx);
|
||||
cb.data += back->bits_offset;
|
||||
cb.format = back->format;
|
||||
|
||||
GGLSurface t;
|
||||
t.version = sizeof(GGLSurface);
|
||||
t.width = front->w;
|
||||
t.height = front->h;
|
||||
t.stride = front->stride;
|
||||
t.data = (GGLubyte*)surface->heapBase(1-backIdx);
|
||||
t.data += front->bits_offset;
|
||||
t.format = front->format;
|
||||
|
||||
//const Region copyback(lcblk->region + 1-backIdx);
|
||||
copyBlt(cb, t, copyback);
|
||||
}
|
||||
}
|
||||
|
||||
// update dirty region
|
||||
surface->setDirtyRegion(newDirtyRegion);
|
||||
}
|
||||
return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR);
|
||||
}
|
||||
|
||||
void SurfaceComposerClient::_signal_server()
|
||||
{
|
||||
mSignalServer->signal();
|
||||
}
|
||||
|
||||
void SurfaceComposerClient::_send_dirty_region(
|
||||
layer_cblk_t* lcblk, const Region& dirty)
|
||||
{
|
||||
const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
|
||||
flat_region_t* flat_region = lcblk->region + index;
|
||||
status_t err = dirty.write(flat_region, sizeof(flat_region_t));
|
||||
if (err < NO_ERROR) {
|
||||
// region doesn't fit, use the bounds
|
||||
const Region reg(dirty.bounds());
|
||||
reg.write(flat_region, sizeof(flat_region_t));
|
||||
}
|
||||
}
|
||||
|
||||
status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface)
|
||||
{
|
||||
Mutex::Autolock _l(surface->getLock());
|
||||
|
||||
SurfaceID index = surface->ID();
|
||||
per_client_cblk_t* const cblk = mControl;
|
||||
status_t err = validateSurface(cblk, surface);
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
Region dirty(surface->dirtyRegion());
|
||||
const Rect& swapRect(surface->swapRectangle());
|
||||
if (swapRect.isValid()) {
|
||||
dirty.set(swapRect);
|
||||
}
|
||||
|
||||
// transmit the dirty region
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[index]);
|
||||
_send_dirty_region(lcblk, dirty);
|
||||
uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
|
||||
if (!(newstate & eNextFlipPending))
|
||||
_signal_server();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t SurfaceComposerClient::unlockSurface(Surface* surface)
|
||||
{
|
||||
Mutex::Autolock _l(surface->getLock());
|
||||
|
||||
SurfaceID index = surface->ID();
|
||||
per_client_cblk_t* const cblk = mControl;
|
||||
status_t err = validateSurface(cblk, surface);
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[index]);
|
||||
cblk->unlock_layer(size_t(index));
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void SurfaceComposerClient::openGlobalTransaction()
|
||||
{
|
||||
Mutex::Autolock _l(gLock);
|
||||
@@ -870,7 +620,7 @@ layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface)
|
||||
{
|
||||
SurfaceID index = surface->ID();
|
||||
per_client_cblk_t* const cblk = mControl;
|
||||
status_t err = validateSurface(cblk, surface.get());
|
||||
status_t err = surface->validate(cblk);
|
||||
if (err != NO_ERROR)
|
||||
return 0;
|
||||
|
||||
@@ -973,7 +723,6 @@ status_t SurfaceComposerClient::setFlags(Surface* surface,
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t SurfaceComposerClient::setTransparentRegionHint(
|
||||
Surface* surface, const Region& transparentRegion)
|
||||
{
|
||||
|
||||
@@ -650,28 +650,26 @@ status_t Parcel::writeWeakBinder(const wp<IBinder>& val)
|
||||
return flatten_binder(ProcessState::self(), val, this);
|
||||
}
|
||||
|
||||
status_t Parcel::writeNativeHandle(const native_handle& handle)
|
||||
status_t Parcel::writeNativeHandle(const native_handle* handle)
|
||||
{
|
||||
if (handle.version != sizeof(native_handle))
|
||||
if (handle->version != sizeof(native_handle))
|
||||
return BAD_TYPE;
|
||||
|
||||
status_t err;
|
||||
err = writeInt32(handle.numFds);
|
||||
err = writeInt32(handle->numFds);
|
||||
if (err != NO_ERROR) return err;
|
||||
|
||||
err = writeInt32(handle.numInts);
|
||||
err = writeInt32(handle->numInts);
|
||||
if (err != NO_ERROR) return err;
|
||||
|
||||
for (int i=0 ; err==NO_ERROR && i<handle.numFds ; i++)
|
||||
err = writeDupFileDescriptor(handle.data[i]);
|
||||
for (int i=0 ; err==NO_ERROR && i<handle->numFds ; i++)
|
||||
err = writeDupFileDescriptor(handle->data[i]);
|
||||
|
||||
if (err != NO_ERROR) {
|
||||
LOGD("write native handle, write dup fd failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = write(handle.data + handle.numFds, sizeof(int)*handle.numInts);
|
||||
|
||||
err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -928,7 +926,7 @@ wp<IBinder> Parcel::readWeakBinder() const
|
||||
}
|
||||
|
||||
|
||||
native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int), void* cookie) const
|
||||
native_handle* Parcel::readNativeHandle() const
|
||||
{
|
||||
int numFds, numInts;
|
||||
status_t err;
|
||||
@@ -937,31 +935,15 @@ native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int)
|
||||
err = readInt32(&numInts);
|
||||
if (err != NO_ERROR) return 0;
|
||||
|
||||
native_handle* h;
|
||||
if (alloc == 0) {
|
||||
size_t size = sizeof(native_handle) + sizeof(int)*(numFds + numInts);
|
||||
h = (native_handle*)malloc(size);
|
||||
h->version = sizeof(native_handle);
|
||||
h->numFds = numFds;
|
||||
h->numInts = numInts;
|
||||
} else {
|
||||
h = alloc(cookie, numFds, numInts);
|
||||
if (h->version != sizeof(native_handle)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
native_handle* h = native_handle_create(numFds, numInts);
|
||||
for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {
|
||||
h->data[i] = dup(readFileDescriptor());
|
||||
if (h->data[i] < 0) err = BAD_VALUE;
|
||||
}
|
||||
|
||||
err = read(h->data + numFds, sizeof(int)*numInts);
|
||||
|
||||
if (err != NO_ERROR) {
|
||||
if (alloc == 0) {
|
||||
free(h);
|
||||
}
|
||||
native_handle_close(h);
|
||||
native_handle_delete(h);
|
||||
h = 0;
|
||||
}
|
||||
return h;
|
||||
|
||||
265
opengl/include/EGL/android_natives.h
Normal file
265
opengl/include/EGL/android_natives.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (C) 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_ANDROID_NATIVES_H
|
||||
#define ANDROID_ANDROID_NATIVES_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
|
||||
(((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d))
|
||||
|
||||
#define ANDROID_NATIVE_WINDOW_MAGIC \
|
||||
ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
|
||||
|
||||
#define ANDROID_NATIVE_BUFFER_MAGIC \
|
||||
ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct android_native_buffer_t;
|
||||
|
||||
enum {
|
||||
/* attributes of this surface or its updater */
|
||||
SURFACE_FLAG_PRESERVE_CONTENT = FRAMEBUFFER_RESERVED0,
|
||||
SURFACE_FLAG_MAPPED = FRAMEBUFFER_FLAG_MAPPED,
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct android_native_base_t
|
||||
{
|
||||
/* a magic value defined by the actual EGL native type */
|
||||
int magic;
|
||||
|
||||
/* the sizeof() of the actual EGL native type */
|
||||
int version;
|
||||
|
||||
void* reserved[4];
|
||||
|
||||
/* reference-counting interface */
|
||||
void (*incRef)(struct android_native_base_t* base);
|
||||
void (*decRef)(struct android_native_base_t* base);
|
||||
};
|
||||
|
||||
|
||||
struct android_native_window_t
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
android_native_window_t()
|
||||
: flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
|
||||
{
|
||||
common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
|
||||
common.version = sizeof(android_native_window_t);
|
||||
memset(common.reserved, 0, sizeof(common.reserved));
|
||||
}
|
||||
#endif
|
||||
|
||||
struct android_native_base_t common;
|
||||
|
||||
/* flags describing some attributes of this surface or its updater */
|
||||
const uint32_t flags;
|
||||
|
||||
/* min swap interval supported by this updated */
|
||||
const int minSwapInterval;
|
||||
|
||||
/* max swap interval supported by this updated */
|
||||
const int maxSwapInterval;
|
||||
|
||||
/* horizontal and vertical resolution in DPI */
|
||||
const float xdpi;
|
||||
const float ydpi;
|
||||
|
||||
/* Some storage reserved for the OEM's driver. */
|
||||
intptr_t oem[4];
|
||||
|
||||
/*
|
||||
* hook called by EGL when the native surface is made current
|
||||
* (eglMakeCurrent()). This hook can be NULL.
|
||||
*/
|
||||
void (*connect)(struct android_native_window_t* window);
|
||||
|
||||
/*
|
||||
* hook called by EGL when the native surface in not current any-longer.
|
||||
* This hook can be NULL.
|
||||
*/
|
||||
void (*disconnect)(struct android_native_window_t* window);
|
||||
|
||||
|
||||
/*
|
||||
* Set the swap interval for this surface.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*setSwapInterval)(struct android_native_window_t* window,
|
||||
int interval);
|
||||
|
||||
|
||||
/*
|
||||
* FIXME: needs documentation for setSwapRectangle
|
||||
* tentative: rect used during queueBuffer to indicate which part of
|
||||
* the screen needs updating.
|
||||
*/
|
||||
int (*setSwapRectangle)(struct android_native_window_t* window,
|
||||
int left, int top, int width, int height);
|
||||
|
||||
|
||||
/*
|
||||
* hook called by EGL to acquire a buffer. After this call, the buffer
|
||||
* is not locked, so its content cannot be modified.
|
||||
* this call may block if no buffers are availlable.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*dequeueBuffer)(struct android_native_window_t* window,
|
||||
struct android_native_buffer_t** buffer);
|
||||
|
||||
/*
|
||||
* hook called by EGL to lock a buffer. This MUST be called before modifying
|
||||
* the content of a buffer. The buffer must have been acquired with
|
||||
* dequeueBuffer first.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*lockBuffer)(struct android_native_window_t* window,
|
||||
struct android_native_buffer_t* buffer);
|
||||
/*
|
||||
* hook called by EGL when modifications to the render buffer are done.
|
||||
* This unlocks and post the buffer.
|
||||
*
|
||||
* Buffers MUST be queued in the same order than they were dequeued.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*queueBuffer)(struct android_native_window_t* window,
|
||||
struct android_native_buffer_t* buffer);
|
||||
|
||||
|
||||
void* reserved_proc[5];
|
||||
};
|
||||
|
||||
|
||||
struct android_native_buffer_t
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
android_native_buffer_t() {
|
||||
common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
|
||||
common.version = sizeof(android_native_buffer_t);
|
||||
memset(common.reserved, 0, sizeof(common.reserved));
|
||||
}
|
||||
#endif
|
||||
|
||||
struct android_native_base_t common;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int stride;
|
||||
int format;
|
||||
int usage;
|
||||
void* bits; // non-zero if buffer is mmaped
|
||||
|
||||
void* reserved[2];
|
||||
|
||||
int (*getHandle)(struct android_native_buffer_t const * base,
|
||||
buffer_handle_t* handle);
|
||||
|
||||
void* reserved_proc[7];
|
||||
};
|
||||
|
||||
|
||||
/* FIXME: this is legacy for pixmaps */
|
||||
struct egl_native_pixmap_t
|
||||
{
|
||||
int32_t version; /* must be 32 */
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t stride;
|
||||
uint8_t* data;
|
||||
uint8_t format;
|
||||
uint8_t rfu[3];
|
||||
union {
|
||||
uint32_t compressedFormat;
|
||||
int32_t vstride;
|
||||
};
|
||||
int32_t reserved;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* This helper class turns an EGL android_native_xxx type into a C++
|
||||
* reference-counted object; with proper type conversions.
|
||||
*/
|
||||
template <typename NATIVE_TYPE, typename TYPE, typename REF>
|
||||
class EGLNativeBase : public NATIVE_TYPE, public REF
|
||||
{
|
||||
protected:
|
||||
typedef EGLNativeBase<NATIVE_TYPE, TYPE, REF> BASE;
|
||||
EGLNativeBase() : NATIVE_TYPE(), REF() {
|
||||
NATIVE_TYPE::common.incRef = incRef;
|
||||
NATIVE_TYPE::common.decRef = decRef;
|
||||
}
|
||||
static inline TYPE* getSelf(NATIVE_TYPE* self) {
|
||||
return static_cast<TYPE*>(self);
|
||||
}
|
||||
static inline TYPE const* getSelf(NATIVE_TYPE const* self) {
|
||||
return static_cast<TYPE const *>(self);
|
||||
}
|
||||
static inline TYPE* getSelf(android_native_base_t* base) {
|
||||
return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));
|
||||
}
|
||||
static inline TYPE const * getSelf(android_native_base_t const* base) {
|
||||
return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));
|
||||
}
|
||||
static void incRef(android_native_base_t* base) {
|
||||
EGLNativeBase* self = getSelf(base);
|
||||
self->incStrong(self);
|
||||
}
|
||||
static void decRef(android_native_base_t* base) {
|
||||
EGLNativeBase* self = getSelf(base);
|
||||
self->decStrong(self);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
#endif // __cplusplus
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* ANDROID_ANDROID_NATIVES_H */
|
||||
@@ -89,12 +89,17 @@ typedef Window EGLNativeWindowType;
|
||||
|
||||
#elif defined(ANDROID)
|
||||
|
||||
#include <EGL/eglnatives.h>
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
typedef struct egl_native_window_t* EGLNativeWindowType;
|
||||
typedef struct android_native_window_t* EGLNativeWindowType;
|
||||
typedef struct egl_native_pixmap_t* EGLNativePixmapType;
|
||||
typedef void* EGLNativeDisplayType;
|
||||
|
||||
#ifndef EGL_ANDROID_image_native_buffer
|
||||
#define EGL_ANDROID_image_native_buffer 1
|
||||
#define EGL_NATIVE_BUFFER_ANDROID 0x6000 /* eglCreateImageKHR target */
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error "Platform not recognized"
|
||||
#endif
|
||||
|
||||
@@ -28,12 +28,6 @@
|
||||
|
||||
#define GL_APIENTRY KHRONOS_APIENTRY
|
||||
|
||||
// XXX: this should probably not be here
|
||||
#define GL_DIRECT_TEXTURE_2D_QUALCOMM 0x7E80
|
||||
|
||||
// XXX: not sure how this is intended to be used
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __glplatform_h_ */
|
||||
|
||||
@@ -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,7 +35,15 @@ 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_LDLIBS := -lpthread -ldl
|
||||
LOCAL_MODULE:= libagl
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,9 @@ 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
|
||||
}
|
||||
|
||||
void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old)
|
||||
@@ -146,7 +149,7 @@ status_t EGLTextureObject::reallocate(
|
||||
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 +180,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)
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -81,6 +81,9 @@ public:
|
||||
GLint crop_rect[4];
|
||||
GLint generate_mipmap;
|
||||
GLint direct;
|
||||
#ifdef LIBAGL_USE_GRALLOC_COPYBITS
|
||||
int copybits_fd;
|
||||
#endif // LIBAGL_USE_GRALLOC_COPYBITS
|
||||
};
|
||||
|
||||
void EGLTextureObject::incStrong(const void* id) const {
|
||||
|
||||
@@ -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) {
|
||||
@@ -1409,7 +1418,7 @@ 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) {
|
||||
@@ -1444,7 +1453,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 +1472,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 +1502,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 +1550,7 @@ void glDeleteBuffers(GLsizei n, const GLuint* buffers)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c->bufferObjectManager->deleteBuffers(n, buffers);
|
||||
c->bufferObjectManager->recycleTokens(n, buffers);
|
||||
}
|
||||
|
||||
370
opengl/libagl/copybit.cpp
Normal file
370
opengl/libagl/copybit.cpp
Normal file
@@ -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
|
||||
|
||||
75
opengl/libagl/copybit.h
Normal file
75
opengl/libagl/copybit.h
Normal file
@@ -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
|
||||
@@ -1,22 +1,20 @@
|
||||
/*
|
||||
/*
|
||||
**
|
||||
** Copyright 2007 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "EGL"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
@@ -35,6 +33,7 @@
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <EGL/android_natives.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
@@ -46,6 +45,10 @@
|
||||
#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 +92,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,7 +143,7 @@ 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 EGLint getWidth() const = 0;
|
||||
@@ -188,39 +191,48 @@ EGLint egl_surface_t::getSwapBehavior() const {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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 EGLint getWidth() const { return buffer->width; }
|
||||
virtual EGLint getHeight() const { return buffer->height; }
|
||||
virtual void* getBits() const;
|
||||
virtual EGLint getHorizontalResolution() const;
|
||||
virtual EGLint getVerticalResolution() const;
|
||||
virtual EGLint getRefreshRate() const;
|
||||
virtual EGLint getSwapBehavior() const;
|
||||
private:
|
||||
egl_native_window_t* nativeWindow;
|
||||
android_native_window_t* nativeWindow;
|
||||
android_native_buffer_t* buffer;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
nativeWindow->common.incRef(&nativeWindow->common);
|
||||
|
||||
nativeWindow->dequeueBuffer(nativeWindow, &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,23 +240,56 @@ egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy,
|
||||
return;
|
||||
}
|
||||
}
|
||||
nativeWindow->incRef(nativeWindow);
|
||||
}
|
||||
egl_window_surface_t::~egl_window_surface_t() {
|
||||
nativeWindow->decRef(nativeWindow);
|
||||
|
||||
// TODO: lockBuffer should rather be executed when the very first
|
||||
// direct rendering occurs.
|
||||
buffer->common.incRef(&buffer->common);
|
||||
nativeWindow->lockBuffer(nativeWindow, buffer);
|
||||
|
||||
// FIXME: we need to gralloc lock the buffer
|
||||
// FIXME: we need to handle the copy-back if needed, but
|
||||
// for now we're a "non preserving" implementation.
|
||||
}
|
||||
|
||||
EGLBoolean egl_window_surface_t::swapBuffers()
|
||||
egl_window_surface_v2_t::~egl_window_surface_v2_t() {
|
||||
if (buffer) {
|
||||
buffer->common.decRef(&buffer->common);
|
||||
}
|
||||
nativeWindow->common.decRef(&nativeWindow->common);
|
||||
}
|
||||
|
||||
EGLBoolean egl_window_surface_v2_t::swapBuffers()
|
||||
{
|
||||
uint32_t flags = nativeWindow->swapBuffers(nativeWindow);
|
||||
if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) {
|
||||
// TODO: this is roughly the code needed for preserving the back buffer
|
||||
// efficiently. dirty is the area that has been modified.
|
||||
//Region newDirty(dirty);
|
||||
//newDirty.andSelf(Rect(nativeWindow->width, nativeWindow->height));
|
||||
//mDirty = newDirty;
|
||||
//const Region copyback(mDirty.subtract(newDirty));
|
||||
//mDisplaySurface->copyFrontToBack(copyback);
|
||||
|
||||
|
||||
nativeWindow->queueBuffer(nativeWindow, buffer);
|
||||
buffer->common.decRef(&buffer->common); buffer = 0;
|
||||
|
||||
nativeWindow->dequeueBuffer(nativeWindow, &buffer);
|
||||
buffer->common.incRef(&buffer->common);
|
||||
|
||||
// TODO: lockBuffer should rather be executed when the very first
|
||||
// direct rendering occurs.
|
||||
nativeWindow->lockBuffer(nativeWindow, buffer);
|
||||
|
||||
|
||||
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);
|
||||
@@ -255,49 +300,81 @@ EGLBoolean egl_window_surface_t::swapBuffers()
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl)
|
||||
#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*)this->buffer->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->getHandle(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*)this->buffer->bits;
|
||||
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;
|
||||
void* egl_window_surface_v2_t::getBits() const {
|
||||
return (GGLubyte*)buffer->bits;
|
||||
}
|
||||
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 {
|
||||
//uint32_t flags = nativeWindow->flags;
|
||||
//if (flags & SURFACE_FLAG_PRESERVE_CONTENT)
|
||||
// return EGL_BUFFER_PRESERVED;
|
||||
// This is now a feature of EGL, currently we don't preserve
|
||||
// the content of the buffers.
|
||||
return EGL_BUFFER_DESTROYED;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -311,7 +388,7 @@ 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; }
|
||||
@@ -347,7 +424,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,7 +453,7 @@ 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; }
|
||||
@@ -407,7 +484,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 +545,11 @@ 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 =
|
||||
"KHR_image_base "
|
||||
// "KHR_image_pixmap "
|
||||
"EGL_ANDROID_image_native_buffer "
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -478,25 +559,45 @@ struct extention_map_t {
|
||||
};
|
||||
|
||||
static const extention_map_t gExtentionMap[] = {
|
||||
{ "glDrawTexsOES", (void(*)())&glDrawTexsOES },
|
||||
{ "glDrawTexiOES", (void(*)())&glDrawTexiOES },
|
||||
{ "glDrawTexfOES", (void(*)())&glDrawTexfOES },
|
||||
{ "glDrawTexxOES", (void(*)())&glDrawTexxOES },
|
||||
{ "glDrawTexsvOES", (void(*)())&glDrawTexsvOES },
|
||||
{ "glDrawTexivOES", (void(*)())&glDrawTexivOES },
|
||||
{ "glDrawTexfvOES", (void(*)())&glDrawTexfvOES },
|
||||
{ "glDrawTexxvOES", (void(*)())&glDrawTexxvOES },
|
||||
{ "glQueryMatrixxOES", (void(*)())&glQueryMatrixxOES },
|
||||
{ "glClipPlanef", (void(*)())&glClipPlanef },
|
||||
{ "glClipPlanex", (void(*)())&glClipPlanex },
|
||||
{ "glBindBuffer", (void(*)())&glBindBuffer },
|
||||
{ "glBufferData", (void(*)())&glBufferData },
|
||||
{ "glBufferSubData", (void(*)())&glBufferSubData },
|
||||
{ "glDeleteBuffers", (void(*)())&glDeleteBuffers },
|
||||
{ "glGenBuffers", (void(*)())&glGenBuffers },
|
||||
{ "glDrawTexsOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
|
||||
{ "glDrawTexiOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
|
||||
{ "glDrawTexfOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
|
||||
{ "glDrawTexxOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
|
||||
{ "glDrawTexsvOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
|
||||
{ "glDrawTexivOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
|
||||
{ "glDrawTexfvOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
|
||||
{ "glDrawTexxvOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
|
||||
{ "glQueryMatrixxOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
|
||||
{ "glEGLImageTargetTexture2DOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
|
||||
{ "glEGLImageTargetRenderbufferStorageOES",
|
||||
(__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
|
||||
{ "glClipPlanef",
|
||||
(__eglMustCastToProperFunctionPointerType)&glClipPlanef },
|
||||
{ "glClipPlanex",
|
||||
(__eglMustCastToProperFunctionPointerType)&glClipPlanex },
|
||||
{ "glBindBuffer",
|
||||
(__eglMustCastToProperFunctionPointerType)&glBindBuffer },
|
||||
{ "glBufferData",
|
||||
(__eglMustCastToProperFunctionPointerType)&glBufferData },
|
||||
{ "glBufferSubData",
|
||||
(__eglMustCastToProperFunctionPointerType)&glBufferSubData },
|
||||
{ "glDeleteBuffers",
|
||||
(__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
|
||||
{ "glGenBuffers",
|
||||
(__eglMustCastToProperFunctionPointerType)&glGenBuffers },
|
||||
};
|
||||
|
||||
/*
|
||||
/*
|
||||
* In the lists below, attributes names MUST be sorted.
|
||||
* Additionally, all configs must be sorted according to
|
||||
* the EGL specification.
|
||||
@@ -507,7 +608,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 },
|
||||
@@ -644,9 +745,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;
|
||||
@@ -658,13 +759,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,
|
||||
@@ -778,28 +879,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:
|
||||
@@ -812,9 +913,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
|
||||
@@ -847,28 +948,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:
|
||||
@@ -900,10 +1001,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;
|
||||
@@ -911,28 +1012,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:
|
||||
@@ -985,7 +1086,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display)
|
||||
egl_display_t& d = egl_display_t::get_display(dpy);
|
||||
d.type = display;
|
||||
return dpy;
|
||||
}
|
||||
}
|
||||
return EGL_NO_DISPLAY;
|
||||
}
|
||||
|
||||
@@ -993,10 +1094,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);
|
||||
@@ -1064,7 +1165,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;
|
||||
@@ -1145,7 +1246,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)
|
||||
@@ -1158,7 +1259,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)
|
||||
@@ -1228,7 +1329,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);
|
||||
@@ -1278,7 +1379,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);
|
||||
|
||||
@@ -1299,6 +1400,8 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: call connect / disconnect on the surface
|
||||
|
||||
ogles_context_t* gl = (ogles_context_t*)ctx;
|
||||
if (makeCurrent(gl) == 0) {
|
||||
if (ctx) {
|
||||
@@ -1407,7 +1510,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);
|
||||
@@ -1540,7 +1643,7 @@ EGLSurface eglCreatePbufferFromClientBuffer(
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Android extensions
|
||||
// EGL_EGLEXT_VERSION 3
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void (*eglGetProcAddress (const char *procname))()
|
||||
@@ -1553,3 +1656,81 @@ 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);
|
||||
|
||||
hw_module_t const* pModule;
|
||||
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
|
||||
return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
|
||||
buffer_handle_t bufferHandle;
|
||||
gralloc_module_t const* module =
|
||||
reinterpret_cast<gralloc_module_t const*>(pModule);
|
||||
if (native_buffer->getHandle(native_buffer, &bufferHandle) < 0)
|
||||
return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
|
||||
if (module->map(module, bufferHandle, &native_buffer->bits) < 0)
|
||||
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);
|
||||
|
||||
hw_module_t const* pModule;
|
||||
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule) == 0) {
|
||||
buffer_handle_t bufferHandle;
|
||||
gralloc_module_t const* module =
|
||||
reinterpret_cast<gralloc_module_t const*>(pModule);
|
||||
if (native_buffer->getHandle(native_buffer, &bufferHandle) == 0) {
|
||||
module->unmap(module, bufferHandle);
|
||||
}
|
||||
}
|
||||
|
||||
native_buffer->common.decRef(&native_buffer->common);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
@@ -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, ©Bits) == 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;
|
||||
|
||||
@@ -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 <EGL/android_natives.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);
|
||||
@@ -255,7 +262,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 +280,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 +289,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 +317,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 +537,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 +588,10 @@ 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;
|
||||
|
||||
const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
|
||||
y = gglIntToFixed(cbSurface.height) - (y + h);
|
||||
w >>= FIXED_BITS;
|
||||
@@ -610,7 +614,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,13 +645,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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// All coordinates are integer, so if we have only one
|
||||
@@ -656,14 +677,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 +707,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 +722,7 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
c->rasterizer.procs.texCoord2i(c, s0, t0);
|
||||
const uint32_t enables = c->rasterizer.state.enables;
|
||||
@@ -711,7 +739,7 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte
|
||||
}
|
||||
|
||||
slow_case:
|
||||
drawTexxOES(
|
||||
drawTexxOESImp(
|
||||
gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z),
|
||||
gglIntToFixed(w), gglIntToFixed(h),
|
||||
c);
|
||||
@@ -749,7 +777,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 +865,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 +973,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 +1037,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 +1045,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 +1055,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 +1079,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 +1159,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 +1212,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 +1222,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 +1231,7 @@ void glCopyTexImage2D(
|
||||
case GL_LUMINANCE:
|
||||
case GL_RGB:
|
||||
format = internalformat;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1235,7 +1251,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 +1261,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 +1311,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 +1381,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 +1435,73 @@ 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;
|
||||
}
|
||||
|
||||
if (native_buffer->bits == NULL) {
|
||||
// this buffer cannot be used with this implementation
|
||||
ogles_error(c, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
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 = (GGLubyte*)native_buffer->bits;
|
||||
|
||||
// bind it to the texture unit
|
||||
sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
|
||||
tex->setSurface(&sur);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
buffer_handle_t handle;
|
||||
if (native_buffer->getHandle(native_buffer, &handle) == 0) {
|
||||
private_handle_t* hand;
|
||||
if ((hand = private_handle_t::dynamicCast(handle)) != NULL) {
|
||||
if (hand->usesPhysicallyContiguousMemory()) {
|
||||
tex->copybits_fd = hand->fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // LIBAGL_USE_GRALLOC_COPYBITS
|
||||
}
|
||||
|
||||
void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
EGL/egl.cpp \
|
||||
EGL/gpu.cpp \
|
||||
EGL/egl.cpp \
|
||||
#
|
||||
|
||||
LOCAL_SHARED_LIBRARIES += libcutils libutils libui
|
||||
@@ -23,6 +22,9 @@ else
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
|
||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
||||
@@ -35,7 +37,6 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
GLES_CM/gl.cpp.arm \
|
||||
GLES_CM/gl_logger.cpp \
|
||||
#
|
||||
|
||||
LOCAL_SHARED_LIBRARIES += libcutils libutils libui libEGL
|
||||
@@ -50,4 +51,7 @@ else
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\"
|
||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "GLLogger"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -38,6 +36,8 @@
|
||||
#include <cutils/memory.h>
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
|
||||
#include "hooks.h"
|
||||
#include "egl_impl.h"
|
||||
@@ -55,7 +55,14 @@ namespace android {
|
||||
static char const * const gVendorString = "Android";
|
||||
static char const * const gVersionString = "1.31 Android META-EGL";
|
||||
static char const * const gClientApiString = "OpenGL ES";
|
||||
static char const * const gExtensionString = "";
|
||||
static char const * const gExtensionString =
|
||||
"EGL_KHR_image "
|
||||
"KHR_image_base "
|
||||
"KHR_image_pixmap "
|
||||
"EGL_ANDROID_image_native_buffer "
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <int MAGIC>
|
||||
struct egl_object_t
|
||||
@@ -69,9 +76,9 @@ private:
|
||||
|
||||
struct egl_display_t : public egl_object_t<'_dpy'>
|
||||
{
|
||||
EGLDisplay dpys[2];
|
||||
EGLConfig* configs[2];
|
||||
EGLint numConfigs[2];
|
||||
EGLDisplay dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
|
||||
EGLConfig* configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
|
||||
EGLint numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
|
||||
EGLint numTotalConfigs;
|
||||
char const* extensionsString;
|
||||
volatile int32_t refs;
|
||||
@@ -81,27 +88,21 @@ struct egl_display_t : public egl_object_t<'_dpy'>
|
||||
char const * clientApi;
|
||||
char const * extensions;
|
||||
};
|
||||
strings_t queryString[2];
|
||||
strings_t queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
|
||||
};
|
||||
|
||||
struct egl_surface_t : public egl_object_t<'_srf'>
|
||||
{
|
||||
egl_surface_t(EGLDisplay dpy, EGLSurface surface,
|
||||
NativeWindowType window, int impl, egl_connection_t const* cnx)
|
||||
: dpy(dpy), surface(surface), window(window), impl(impl), cnx(cnx)
|
||||
int impl, egl_connection_t const* cnx)
|
||||
: dpy(dpy), surface(surface), impl(impl), cnx(cnx)
|
||||
{
|
||||
// NOTE: window must be incRef'ed and connected already
|
||||
}
|
||||
~egl_surface_t() {
|
||||
if (window) {
|
||||
if (window->disconnect)
|
||||
window->disconnect(window);
|
||||
window->decRef(window);
|
||||
}
|
||||
}
|
||||
EGLDisplay dpy;
|
||||
EGLSurface surface;
|
||||
NativeWindowType window;
|
||||
int impl;
|
||||
egl_connection_t const* cnx;
|
||||
};
|
||||
@@ -121,6 +122,18 @@ struct egl_context_t : public egl_object_t<'_ctx'>
|
||||
egl_connection_t const* cnx;
|
||||
};
|
||||
|
||||
struct egl_image_t : public egl_object_t<'_img'>
|
||||
{
|
||||
egl_image_t(EGLDisplay dpy, EGLContext context)
|
||||
: dpy(dpy), context(context)
|
||||
{
|
||||
memset(images, 0, sizeof(images));
|
||||
}
|
||||
EGLDisplay dpy;
|
||||
EGLConfig context;
|
||||
EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
|
||||
};
|
||||
|
||||
struct tls_t
|
||||
{
|
||||
tls_t() : error(EGL_SUCCESS), ctx(0) { }
|
||||
@@ -156,7 +169,7 @@ static char const * const egl_names[] = {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
egl_connection_t gEGLImpl[2];
|
||||
egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
|
||||
static egl_display_t gDisplay[NUM_DISPLAYS];
|
||||
static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_key_t gEGLThreadLocalStorageKey = -1;
|
||||
@@ -261,14 +274,8 @@ EGLContext getContext() {
|
||||
return tls->ctx;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class ISurfaceComposer;
|
||||
const sp<ISurfaceComposer>& getSurfaceFlinger();
|
||||
request_gpu_t* gpu_acquire(void* user);
|
||||
int gpu_release(void*, request_gpu_t* gpu);
|
||||
|
||||
static __attribute__((noinline))
|
||||
void *load_driver(const char* driver, gl_hooks_t* hooks)
|
||||
{
|
||||
@@ -278,42 +285,59 @@ void *load_driver(const char* driver, gl_hooks_t* hooks)
|
||||
driver, dlerror());
|
||||
|
||||
if (dso) {
|
||||
void** curr;
|
||||
// first find the symbol for eglGetProcAddress
|
||||
|
||||
typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)(
|
||||
const char*);
|
||||
|
||||
getProcAddressType getProcAddress =
|
||||
(getProcAddressType)dlsym(dso, "eglGetProcAddress");
|
||||
|
||||
LOGE_IF(!getProcAddress,
|
||||
"can't find eglGetProcAddress() in %s", driver);
|
||||
|
||||
__eglMustCastToProperFunctionPointerType* curr;
|
||||
char const * const * api;
|
||||
gl_hooks_t::gl_t* gl = &hooks->gl;
|
||||
curr = (void**)gl;
|
||||
api = gl_names;
|
||||
while (*api) {
|
||||
void* f = dlsym(dso, *api);
|
||||
//LOGD("<%s> @ 0x%p", *api, f);
|
||||
if (f == NULL) {
|
||||
//LOGW("<%s> not found in %s", *api, driver);
|
||||
f = (void*)gl_unimplemented;
|
||||
}
|
||||
*curr++ = f;
|
||||
api++;
|
||||
}
|
||||
|
||||
gl_hooks_t::egl_t* egl = &hooks->egl;
|
||||
curr = (void**)egl;
|
||||
curr = (__eglMustCastToProperFunctionPointerType*)egl;
|
||||
api = egl_names;
|
||||
while (*api) {
|
||||
void* f = dlsym(dso, *api);
|
||||
char const * name = *api;
|
||||
__eglMustCastToProperFunctionPointerType f =
|
||||
(__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
|
||||
if (f == NULL) {
|
||||
//LOGW("<%s> not found in %s", *api, driver);
|
||||
f = (void*)0;
|
||||
// couldn't find the entry-point, use eglGetProcAddress()
|
||||
f = getProcAddress(name);
|
||||
if (f == NULL) {
|
||||
f = (__eglMustCastToProperFunctionPointerType)0;
|
||||
}
|
||||
}
|
||||
*curr++ = f;
|
||||
api++;
|
||||
}
|
||||
|
||||
// hook this driver up with surfaceflinger if needed
|
||||
register_gpu_t register_gpu =
|
||||
(register_gpu_t)dlsym(dso, "oem_register_gpu");
|
||||
|
||||
if (register_gpu != NULL) {
|
||||
if (getSurfaceFlinger() != 0) {
|
||||
register_gpu(dso, gpu_acquire, gpu_release);
|
||||
|
||||
gl_hooks_t::gl_t* gl = &hooks->gl;
|
||||
curr = (__eglMustCastToProperFunctionPointerType*)gl;
|
||||
api = gl_names;
|
||||
while (*api) {
|
||||
char const * name = *api;
|
||||
// if the function starts with '__' it's a special case that
|
||||
// uses a wrapper. skip the '__' when looking into the real lib.
|
||||
if (name[0] == '_' && name[1] == '_') {
|
||||
name += 2;
|
||||
}
|
||||
__eglMustCastToProperFunctionPointerType f =
|
||||
(__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
|
||||
if (f == NULL) {
|
||||
// couldn't find the entry-point, use eglGetProcAddress()
|
||||
f = getProcAddress(name);
|
||||
if (f == NULL) {
|
||||
f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
|
||||
}
|
||||
}
|
||||
*curr++ = f;
|
||||
api++;
|
||||
}
|
||||
}
|
||||
return dso;
|
||||
@@ -365,6 +389,14 @@ struct extention_map_t {
|
||||
};
|
||||
|
||||
static const extention_map_t gExtentionMap[] = {
|
||||
{ "eglLockSurfaceKHR",
|
||||
(__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
|
||||
{ "eglUnlockSurfaceKHR",
|
||||
(__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
|
||||
{ "eglCreateImageKHR",
|
||||
(__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
|
||||
{ "eglDestroyImageKHR",
|
||||
(__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
|
||||
};
|
||||
|
||||
static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS];
|
||||
@@ -382,6 +414,12 @@ static void(*findProcAddress(const char* name,
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* To "loose" the GPU, use something like
|
||||
* gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST];
|
||||
*
|
||||
*/
|
||||
|
||||
static int gl_context_lost() {
|
||||
setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
|
||||
return 0;
|
||||
@@ -429,18 +467,24 @@ egl_display_t* get_display(EGLDisplay dpy)
|
||||
return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
|
||||
}
|
||||
|
||||
static inline
|
||||
egl_surface_t* get_surface(EGLSurface surface)
|
||||
{
|
||||
egl_surface_t* s = (egl_surface_t *)surface;
|
||||
return s;
|
||||
template<typename NATIVE, typename EGL>
|
||||
static inline NATIVE* egl_to_native_cast(EGL arg) {
|
||||
return reinterpret_cast<NATIVE*>(arg);
|
||||
}
|
||||
|
||||
static inline
|
||||
egl_context_t* get_context(EGLContext context)
|
||||
{
|
||||
egl_context_t* c = (egl_context_t *)context;
|
||||
return c;
|
||||
egl_surface_t* get_surface(EGLSurface surface) {
|
||||
return egl_to_native_cast<egl_surface_t>(surface);
|
||||
}
|
||||
|
||||
static inline
|
||||
egl_context_t* get_context(EGLContext context) {
|
||||
return egl_to_native_cast<egl_context_t>(context);
|
||||
}
|
||||
|
||||
static inline
|
||||
egl_image_t* get_image(EGLImageKHR image) {
|
||||
return egl_to_native_cast<egl_image_t>(image);
|
||||
}
|
||||
|
||||
static egl_connection_t* validate_display_config(
|
||||
@@ -451,7 +495,7 @@ static egl_connection_t* validate_display_config(
|
||||
if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
|
||||
|
||||
impl = uintptr_t(config)>>24;
|
||||
if (uint32_t(impl) >= 2) {
|
||||
if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) {
|
||||
return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
|
||||
}
|
||||
index = uintptr_t(config) & 0xFFFFFF;
|
||||
@@ -491,13 +535,26 @@ static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using namespace android;
|
||||
EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
|
||||
{
|
||||
EGLContext context = getContext();
|
||||
if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
|
||||
egl_context_t const * const c = get_context(context);
|
||||
if (!c->isValid())
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
|
||||
EGLDisplay eglGetDisplay(NativeDisplayType display)
|
||||
egl_image_t const * const i = get_image(image);
|
||||
if (!i->isValid())
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
|
||||
return i->images[c->impl];
|
||||
}
|
||||
|
||||
|
||||
EGLDisplay egl_init_displays(NativeDisplayType display)
|
||||
{
|
||||
if (sEarlyInitState) {
|
||||
return EGL_NO_DISPLAY;
|
||||
@@ -510,7 +567,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display)
|
||||
|
||||
EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
|
||||
egl_display_t* d = &gDisplay[index];
|
||||
|
||||
|
||||
// dynamically load all our EGL implementations for that display
|
||||
// and call into the real eglGetGisplay()
|
||||
egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
|
||||
@@ -530,7 +587,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display)
|
||||
property_get("debug.egl.hw", value, "1");
|
||||
if (atoi(value) != 0) {
|
||||
cnx->hooks = &gHooks[IMPL_HARDWARE];
|
||||
cnx->dso = load_driver("libhgl.so", cnx->hooks);
|
||||
cnx->dso = load_driver("libhgl2.so", cnx->hooks);
|
||||
} else {
|
||||
LOGD("3D hardware acceleration is disabled");
|
||||
}
|
||||
@@ -573,6 +630,18 @@ EGLDisplay eglGetDisplay(NativeDisplayType display)
|
||||
return dpy;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using namespace android;
|
||||
|
||||
EGLDisplay eglGetDisplay(NativeDisplayType display)
|
||||
{
|
||||
return egl_init_displays(display);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Initialization
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -594,7 +663,7 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
|
||||
// build our own extension string first, based on the extension we know
|
||||
// and the extension supported by our client implementation
|
||||
dp->extensionsString = strdup(gExtensionString);
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
cnx->major = -1;
|
||||
cnx->minor = -1;
|
||||
@@ -624,7 +693,7 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
|
||||
}
|
||||
|
||||
EGLBoolean res = EGL_FALSE;
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
|
||||
EGLint n;
|
||||
@@ -663,7 +732,7 @@ EGLBoolean eglTerminate(EGLDisplay dpy)
|
||||
return EGL_TRUE;
|
||||
|
||||
EGLBoolean res = EGL_FALSE;
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso) {
|
||||
cnx->hooks->egl.eglTerminate(dp->dpys[i]);
|
||||
@@ -706,7 +775,7 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy,
|
||||
return EGL_TRUE;
|
||||
}
|
||||
GLint n = 0;
|
||||
for (int j=0 ; j<2 ; j++) {
|
||||
for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
|
||||
for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) {
|
||||
*configs++ = MAKE_CONFIG(j, i);
|
||||
config_size--;
|
||||
@@ -794,7 +863,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
|
||||
return res;
|
||||
}
|
||||
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso) {
|
||||
if (cnx->hooks->egl.eglChooseConfig(
|
||||
@@ -854,26 +923,12 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
|
||||
int i=0, index=0;
|
||||
egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
|
||||
if (cnx) {
|
||||
// window must be connected upon calling underlying
|
||||
// eglCreateWindowSurface
|
||||
if (window) {
|
||||
window->incRef(window);
|
||||
if (window->connect)
|
||||
window->connect(window);
|
||||
}
|
||||
|
||||
EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface(
|
||||
dp->dpys[i], dp->configs[i][index], window, attrib_list);
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
egl_surface_t* s = new egl_surface_t(dpy, surface, window, i, cnx);
|
||||
egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
|
||||
return s;
|
||||
}
|
||||
|
||||
// something went wrong, disconnect and free window
|
||||
// (will disconnect() automatically)
|
||||
if (window) {
|
||||
window->decRef(window);
|
||||
}
|
||||
}
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
@@ -889,7 +944,7 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
|
||||
EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface(
|
||||
dp->dpys[i], dp->configs[i][index], pixmap, attrib_list);
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx);
|
||||
egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -906,7 +961,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
|
||||
EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface(
|
||||
dp->dpys[i], dp->configs[i][index], attrib_list);
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx);
|
||||
egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1107,7 +1162,7 @@ EGLBoolean eglWaitNative(EGLint engine)
|
||||
EGLint eglGetError(void)
|
||||
{
|
||||
EGLint result = EGL_SUCCESS;
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
EGLint err = EGL_SUCCESS;
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso)
|
||||
@@ -1120,8 +1175,15 @@ EGLint eglGetError(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
void (*eglGetProcAddress(const char *procname))()
|
||||
__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
|
||||
{
|
||||
// eglGetProcAddress() could be the very first function called
|
||||
// in which case we must make sure we've initialized ourselves, this
|
||||
// happens the first time egl_get_display() is called.
|
||||
|
||||
if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY)
|
||||
return NULL;
|
||||
|
||||
__eglMustCastToProperFunctionPointerType addr;
|
||||
addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
|
||||
if (addr) return addr;
|
||||
@@ -1133,7 +1195,7 @@ void (*eglGetProcAddress(const char *procname))()
|
||||
|
||||
addr = 0;
|
||||
int slot = -1;
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso) {
|
||||
if (cnx->hooks->egl.eglGetProcAddress) {
|
||||
@@ -1266,7 +1328,7 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
|
||||
if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
|
||||
|
||||
EGLBoolean res = EGL_TRUE;
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso) {
|
||||
if (cnx->hooks->egl.eglSwapInterval) {
|
||||
@@ -1309,7 +1371,7 @@ EGLBoolean eglBindAPI(EGLenum api)
|
||||
{
|
||||
// bind this API on all EGLs
|
||||
EGLBoolean res = EGL_TRUE;
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso) {
|
||||
if (cnx->hooks->egl.eglBindAPI) {
|
||||
@@ -1324,7 +1386,7 @@ EGLBoolean eglBindAPI(EGLenum api)
|
||||
|
||||
EGLenum eglQueryAPI(void)
|
||||
{
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso) {
|
||||
if (cnx->hooks->egl.eglQueryAPI) {
|
||||
@@ -1340,7 +1402,7 @@ EGLenum eglQueryAPI(void)
|
||||
|
||||
EGLBoolean eglReleaseThread(void)
|
||||
{
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (cnx->dso) {
|
||||
if (cnx->hooks->egl.eglReleaseThread) {
|
||||
@@ -1366,3 +1428,124 @@ EGLSurface eglCreatePbufferFromClientBuffer(
|
||||
}
|
||||
return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// EGL_EGLEXT_VERSION 3
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
EGLBoolean result = EGL_FALSE;
|
||||
if (!validate_display_surface(dpy, surface))
|
||||
return result;
|
||||
|
||||
egl_display_t const * const dp = get_display(dpy);
|
||||
egl_surface_t const * const s = get_surface(surface);
|
||||
|
||||
if (s->cnx->hooks->egl.eglLockSurfaceKHR) {
|
||||
result = s->cnx->hooks->egl.eglLockSurfaceKHR(
|
||||
dp->dpys[s->impl], s->surface, attrib_list);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
|
||||
{
|
||||
EGLBoolean result = EGL_FALSE;
|
||||
if (!validate_display_surface(dpy, surface))
|
||||
return result;
|
||||
|
||||
egl_display_t const * const dp = get_display(dpy);
|
||||
egl_surface_t const * const s = get_surface(surface);
|
||||
|
||||
if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) {
|
||||
result = s->cnx->hooks->egl.eglUnlockSurfaceKHR(
|
||||
dp->dpys[s->impl], s->surface);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
|
||||
EGLClientBuffer buffer, const EGLint *attrib_list)
|
||||
{
|
||||
if (ctx != EGL_NO_CONTEXT) {
|
||||
if (!validate_display_context(dpy, ctx))
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
egl_display_t const * const dp = get_display(dpy);
|
||||
egl_context_t * const c = get_context(ctx);
|
||||
// since we have an EGLContext, we know which implementation to use
|
||||
EGLImageKHR image = c->cnx->hooks->egl.eglCreateImageKHR(
|
||||
dp->dpys[c->impl], c->context, target, buffer, attrib_list);
|
||||
if (image == EGL_NO_IMAGE_KHR)
|
||||
return image;
|
||||
|
||||
egl_image_t* result = new egl_image_t(dpy, ctx);
|
||||
result->images[c->impl] = image;
|
||||
return (EGLImageKHR)result;
|
||||
} else {
|
||||
// EGL_NO_CONTEXT is a valid parameter
|
||||
egl_display_t const * const dp = get_display(dpy);
|
||||
if (dp == 0) {
|
||||
return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
|
||||
}
|
||||
// since we don't have a way to know which implementation to call,
|
||||
// we're calling all of them
|
||||
|
||||
EGLImageKHR implImages[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
|
||||
bool success = false;
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
implImages[i] = EGL_NO_IMAGE_KHR;
|
||||
if (cnx->dso) {
|
||||
if (cnx->hooks->egl.eglCreateImageKHR) {
|
||||
implImages[i] = cnx->hooks->egl.eglCreateImageKHR(
|
||||
dp->dpys[i], ctx, target, buffer, attrib_list);
|
||||
if (implImages[i] != EGL_NO_IMAGE_KHR) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!success)
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
|
||||
egl_image_t* result = new egl_image_t(dpy, ctx);
|
||||
memcpy(result->images, implImages, sizeof(implImages));
|
||||
return (EGLImageKHR)result;
|
||||
}
|
||||
}
|
||||
|
||||
EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
|
||||
{
|
||||
egl_display_t const * const dp = get_display(dpy);
|
||||
if (dp == 0) {
|
||||
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
|
||||
}
|
||||
|
||||
egl_image_t* image = get_image(img);
|
||||
if (!image->isValid()) {
|
||||
return setError(EGL_BAD_PARAMETER, EGL_FALSE);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
|
||||
egl_connection_t* const cnx = &gEGLImpl[i];
|
||||
if (image->images[i] != EGL_NO_IMAGE_KHR) {
|
||||
if (cnx->dso) {
|
||||
if (cnx->hooks->egl.eglCreateImageKHR) {
|
||||
if (cnx->hooks->egl.eglDestroyImageKHR(
|
||||
dp->dpys[i], image->images[i])) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!success)
|
||||
return EGL_FALSE;
|
||||
|
||||
delete image;
|
||||
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "GLES_CM"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -29,6 +27,7 @@
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include "hooks.h"
|
||||
#include "egl_impl.h"
|
||||
|
||||
using namespace android;
|
||||
|
||||
@@ -57,13 +56,6 @@ void glVertexPointerBounds(GLint size, GLenum type,
|
||||
// Actual GL entry-points
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if GL_LOGGER
|
||||
# include "gl_logger.h"
|
||||
# define GL_LOGGER_IMPL(_x) _x
|
||||
#else
|
||||
# define GL_LOGGER_IMPL(_x)
|
||||
#endif
|
||||
|
||||
#undef API_ENTRY
|
||||
#undef CALL_GL_API
|
||||
#undef CALL_GL_API_RETURN
|
||||
@@ -96,16 +88,15 @@ void glVertexPointerBounds(GLint size, GLenum type,
|
||||
|
||||
#define CALL_GL_API(_api, ...) \
|
||||
gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
|
||||
GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); ) \
|
||||
_c->_api(__VA_ARGS__)
|
||||
|
||||
#define CALL_GL_API_RETURN(_api, ...) \
|
||||
gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
|
||||
GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); ) \
|
||||
return _c->_api(__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "gl_api.in"
|
||||
}
|
||||
@@ -114,3 +105,27 @@ extern "C" {
|
||||
#undef CALL_GL_API
|
||||
#undef CALL_GL_API_RETURN
|
||||
|
||||
|
||||
/*
|
||||
* These GL calls are special because they need to EGL to retrieve some
|
||||
* informations before they can execute.
|
||||
*/
|
||||
|
||||
extern "C" void __glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
|
||||
extern "C" void __glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
|
||||
|
||||
|
||||
void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
|
||||
{
|
||||
GLeglImageOES implImage =
|
||||
(GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
|
||||
__glEGLImageTargetTexture2DOES(target, implImage);
|
||||
}
|
||||
|
||||
void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
|
||||
{
|
||||
GLeglImageOES implImage =
|
||||
(GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
|
||||
__glEGLImageTargetRenderbufferStorageOES(target, image);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,3 +43,10 @@ EGL_ENTRY(EGLSurface, eglCreatePbufferFromClientBuffer, EGLDisplay, EGLenum, EGL
|
||||
/* EGL 1.3 */
|
||||
|
||||
/* EGL 1.4 */
|
||||
|
||||
/* EGL_EGLEXT_VERSION 3 */
|
||||
|
||||
EGL_ENTRY(EGLBoolean, eglLockSurfaceKHR, EGLDisplay, EGLSurface, const EGLint *)
|
||||
EGL_ENTRY(EGLBoolean, eglUnlockSurfaceKHR, EGLDisplay, EGLSurface)
|
||||
EGL_ENTRY(EGLImageKHR, eglCreateImageKHR, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *)
|
||||
EGL_ENTRY(EGLBoolean, eglDestroyImageKHR, EGLDisplay, EGLImageKHR)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
namespace android {
|
||||
@@ -36,6 +37,8 @@ struct egl_connection_t
|
||||
int unavailable;
|
||||
};
|
||||
|
||||
EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -15,30 +15,30 @@ GL_ENTRY(void, glColorMask, GLboolean, GLboolean, GLboolean, GLboolean)
|
||||
GL_ENTRY(void, glDepthMask, GLboolean)
|
||||
GL_ENTRY(void, glStencilMask, GLuint)
|
||||
GL_ENTRY(void, glDepthFunc, GLenum)
|
||||
GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
|
||||
GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
|
||||
GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
|
||||
GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
|
||||
GL_ENTRY(void, glLogicOp, GLenum opcode)
|
||||
GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
|
||||
GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
|
||||
GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
|
||||
GL_ENTRY(void, glClear, GLbitfield mask)
|
||||
GL_ENTRY(void, glClearColor, GLclampf r, GLclampf g, GLclampf b, GLclampf a)
|
||||
GL_ENTRY(void, glClearColorx, GLclampx r, GLclampx g, GLclampx b, GLclampx a)
|
||||
GL_ENTRY(void, glClearDepthf, GLclampf depth)
|
||||
GL_ENTRY(void, glClearDepthx, GLclampx depth)
|
||||
GL_ENTRY(void, glClearStencil, GLint s)
|
||||
GL_ENTRY(void, glDepthRangef, GLclampf, GLclampf)
|
||||
GL_ENTRY(void, glDepthRangex, GLclampx, GLclampx)
|
||||
GL_ENTRY(void, glPolygonOffset, GLfloat, GLfloat)
|
||||
GL_ENTRY(void, glPolygonOffsetx, GLfixed, GLfixed)
|
||||
GL_ENTRY(void, glLogicOp, GLenum)
|
||||
GL_ENTRY(void, glAlphaFuncx, GLenum, GLclampx)
|
||||
GL_ENTRY(void, glAlphaFunc, GLenum, GLclampf)
|
||||
GL_ENTRY(void, glBlendFunc, GLenum, GLenum)
|
||||
GL_ENTRY(void, glClear, GLbitfield)
|
||||
GL_ENTRY(void, glClearColor, GLclampf, GLclampf, GLclampf, GLclampf)
|
||||
GL_ENTRY(void, glClearColorx, GLclampx, GLclampx, GLclampx, GLclampx)
|
||||
GL_ENTRY(void, glClearDepthf, GLclampf)
|
||||
GL_ENTRY(void, glClearDepthx, GLclampx)
|
||||
GL_ENTRY(void, glClearStencil, GLint)
|
||||
GL_ENTRY(void, glPointSize, GLfloat)
|
||||
GL_ENTRY(void, glPointSizex, GLfixed)
|
||||
GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
|
||||
GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
|
||||
GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
|
||||
GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
|
||||
GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
|
||||
GL_ENTRY(void, glHint, GLenum, GLenum mode)
|
||||
GL_ENTRY(void, glLineWidth, GLfloat width)
|
||||
GL_ENTRY(void, glLineWidthx, GLfixed width)
|
||||
GL_ENTRY(void, glSampleCoverage, GLclampf, GLboolean)
|
||||
GL_ENTRY(void, glSampleCoveragex, GLclampx, GLboolean)
|
||||
GL_ENTRY(void, glStencilFunc, GLenum, GLint, GLuint)
|
||||
GL_ENTRY(void, glStencilOp, GLenum, GLenum, GLenum)
|
||||
GL_ENTRY(void, glScissor, GLint, GLint, GLsizei, GLsizei)
|
||||
GL_ENTRY(void, glHint, GLenum, GLenum)
|
||||
GL_ENTRY(void, glLineWidth, GLfloat)
|
||||
GL_ENTRY(void, glLineWidthx, GLfixed)
|
||||
GL_ENTRY(void, glShadeModel, GLenum)
|
||||
GL_ENTRY(void, glLightModelf, GLenum, GLfloat)
|
||||
GL_ENTRY(void, glLightModelfv, GLenum, const GLfloat *)
|
||||
@@ -63,12 +63,12 @@ GL_ENTRY(void, glTexCoordPointer, GLint, GLenum, GLsizei, const GLvoid *)
|
||||
GL_ENTRY(void, glEnableClientState, GLenum)
|
||||
GL_ENTRY(void, glDisableClientState, GLenum)
|
||||
GL_ENTRY(void, glClientActiveTexture, GLenum)
|
||||
GL_ENTRY(void, glDrawArrays, GLenum, GLint first, GLsizei)
|
||||
GL_ENTRY(void, glDrawArrays, GLenum, GLint, GLsizei)
|
||||
GL_ENTRY(void, glDrawElements, GLenum, GLsizei, GLenum, const GLvoid *)
|
||||
GL_ENTRY(void, glLoadIdentity, void)
|
||||
GL_ENTRY(void, glLoadMatrixf, const GLfloat*)
|
||||
GL_ENTRY(void, glLoadMatrixx, const GLfixed*)
|
||||
GL_ENTRY(void, glMatrixMode, GLenum mode)
|
||||
GL_ENTRY(void, glMatrixMode, GLenum)
|
||||
GL_ENTRY(void, glMultMatrixf, const GLfloat*)
|
||||
GL_ENTRY(void, glMultMatrixx, const GLfixed*)
|
||||
GL_ENTRY(void, glPopMatrix, void)
|
||||
@@ -87,7 +87,7 @@ GL_ENTRY(void, glViewport, GLint, GLint, GLsizei, GLsizei)
|
||||
GL_ENTRY(void, glActiveTexture, GLenum)
|
||||
GL_ENTRY(void, glBindTexture, GLenum, GLuint)
|
||||
GL_ENTRY(void, glGenTextures, GLsizei, GLuint*)
|
||||
GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *)
|
||||
GL_ENTRY(void, glDeleteTextures, GLsizei, const GLuint *)
|
||||
GL_ENTRY(void, glMultiTexCoord4f, GLenum, GLfloat, GLfloat, GLfloat, GLfloat)
|
||||
GL_ENTRY(void, glMultiTexCoord4x, GLenum, GLfixed, GLfixed, GLfixed, GLfixed)
|
||||
GL_ENTRY(void, glPixelStorei, GLenum, GLint)
|
||||
@@ -106,8 +106,8 @@ GL_ENTRY(void, glTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, G
|
||||
GL_ENTRY(void, glReadPixels, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *)
|
||||
|
||||
// 1.1 additions
|
||||
GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat*)
|
||||
GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed*)
|
||||
GL_ENTRY(void, glClipPlanef, GLenum, const GLfloat*)
|
||||
GL_ENTRY(void, glClipPlanex, GLenum, const GLfixed*)
|
||||
GL_ENTRY(void, glBindBuffer, GLenum, GLuint)
|
||||
GL_ENTRY(void, glBufferData, GLenum, GLsizeiptr, const GLvoid*, GLenum)
|
||||
GL_ENTRY(void, glBufferSubData, GLenum, GLintptr, GLsizeiptr, const GLvoid*)
|
||||
@@ -144,7 +144,7 @@ GL_ENTRY(void, glTexParameterfv, GLenum, GLenum, const GLfloat *)
|
||||
GL_ENTRY(void, glTexParameteriv, GLenum, GLenum, const GLint *)
|
||||
GL_ENTRY(void, glTexParameteri, GLenum, GLenum, GLint)
|
||||
GL_ENTRY(void, glTexParameterxv, GLenum, GLenum, const GLfixed *)
|
||||
GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid*)
|
||||
GL_ENTRY(void, glPointSizePointerOES, GLenum, GLsizei, const GLvoid*)
|
||||
|
||||
// Extensions
|
||||
GL_ENTRY(void, glDrawTexsOES, GLshort, GLshort, GLshort, GLshort, GLshort)
|
||||
@@ -155,5 +155,40 @@ GL_ENTRY(void, glDrawTexsvOES, const GLshort*)
|
||||
GL_ENTRY(void, glDrawTexivOES, const GLint*)
|
||||
GL_ENTRY(void, glDrawTexfvOES, const GLfloat*)
|
||||
GL_ENTRY(void, glDrawTexxvOES, const GLfixed*)
|
||||
GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed* mantissa, GLint* exponent)
|
||||
|
||||
GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed*, GLint*)
|
||||
GL_ENTRY(void, __glEGLImageTargetTexture2DOES, GLenum, GLeglImageOES)
|
||||
GL_ENTRY(void, __glEGLImageTargetRenderbufferStorageOES, GLenum, GLeglImageOES)
|
||||
GL_ENTRY(void, glBlendEquationSeparateOES, GLenum, GLenum)
|
||||
GL_ENTRY(void, glBlendFuncSeparateOES, GLenum, GLenum, GLenum, GLenum)
|
||||
GL_ENTRY(void, glBlendEquationOES, GLenum)
|
||||
GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint)
|
||||
GL_ENTRY(void, glBindRenderbufferOES, GLenum, GLuint)
|
||||
GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei, const GLuint*)
|
||||
GL_ENTRY(void, glGenRenderbuffersOES, GLsizei, GLuint*)
|
||||
GL_ENTRY(void, glRenderbufferStorageOES, GLenum, GLenum, GLsizei, GLsizei)
|
||||
GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum, GLenum, GLint*)
|
||||
GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint)
|
||||
GL_ENTRY(void, glBindFramebufferOES, GLenum, GLuint)
|
||||
GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei, const GLuint*)
|
||||
GL_ENTRY(void, glGenFramebuffersOES, GLsizei, GLuint*)
|
||||
GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum)
|
||||
GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum, GLenum, GLenum, GLuint)
|
||||
GL_ENTRY(void, glFramebufferTexture2DOES, GLenum, GLenum, GLenum, GLuint, GLint)
|
||||
GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum, GLenum, GLenum, GLint*)
|
||||
GL_ENTRY(void, glGenerateMipmapOES, GLenum)
|
||||
GL_ENTRY(void*, glMapBufferOES, GLenum, GLenum)
|
||||
GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum)
|
||||
GL_ENTRY(void, glGetBufferPointervOES, GLenum, GLenum, void**)
|
||||
GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint)
|
||||
GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
|
||||
GL_ENTRY(void, glMatrixIndexPointerOES, GLint, GLenum, GLsizei, const GLvoid *)
|
||||
GL_ENTRY(void, glWeightPointerOES, GLint, GLenum, GLsizei, const GLvoid *)
|
||||
GL_ENTRY(void, glTexGenfOES, GLenum, GLenum, GLfloat)
|
||||
GL_ENTRY(void, glTexGenfvOES, GLenum, GLenum, const GLfloat *)
|
||||
GL_ENTRY(void, glTexGeniOES, GLenum, GLenum, GLint)
|
||||
GL_ENTRY(void, glTexGenivOES, GLenum, GLenum, const GLint *)
|
||||
GL_ENTRY(void, glTexGenxOES, GLenum, GLenum, GLfixed)
|
||||
GL_ENTRY(void, glTexGenxvOES, GLenum, GLenum, const GLfixed *)
|
||||
GL_ENTRY(void, glGetTexGenfvOES, GLenum, GLenum, GLfloat *)
|
||||
GL_ENTRY(void, glGetTexGenivOES, GLenum, GLenum, GLint *)
|
||||
GL_ENTRY(void, glGetTexGenxvOES, GLenum, GLenum, GLfixed *)
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
#define GL_LOGGER 0
|
||||
#if !defined(__arm__)
|
||||
#define USE_SLOW_BINDING 1
|
||||
#else
|
||||
@@ -35,7 +36,7 @@
|
||||
#define MAX_NUMBER_OF_GL_EXTENSIONS 32
|
||||
|
||||
|
||||
#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && !GL_LOGGER && __OPTIMIZE__
|
||||
#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && __OPTIMIZE__
|
||||
#define USE_FAST_TLS_KEY 1
|
||||
#else
|
||||
#define USE_FAST_TLS_KEY 0
|
||||
@@ -55,7 +56,10 @@ const unsigned int NUM_DISPLAYS = 1;
|
||||
enum {
|
||||
IMPL_HARDWARE = 0,
|
||||
IMPL_SOFTWARE,
|
||||
IMPL_CONTEXT_LOST,
|
||||
|
||||
IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
|
||||
|
||||
IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
|
||||
IMPL_NO_CONTEXT,
|
||||
|
||||
IMPL_NUM_IMPLEMENTATIONS
|
||||
|
||||
51
opengl/libs/tools/glapigen
Executable file
51
opengl/libs/tools/glapigen
Executable file
@@ -0,0 +1,51 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
use strict;
|
||||
|
||||
my $lineNum = 0;
|
||||
while (my $line = <>) {
|
||||
$lineNum += 1;
|
||||
next if $line =~ /^\//;
|
||||
next if $line =~ /^#/;
|
||||
next if $line =~ /^\s*$/;
|
||||
if ($line !~ /^GL_ENTRY\(([^,]+),\s*([^,]+),\s*([^)]+)\)/) {
|
||||
printf STDERR "Cannot parse line number $lineNum:\n$line";
|
||||
next;
|
||||
}
|
||||
my $type = $1;
|
||||
my $name = $2;
|
||||
my $args = $3;
|
||||
|
||||
printf("%s API_ENTRY(%s)(", $type, $name);
|
||||
my @args = split ',', $args;
|
||||
|
||||
my $len = scalar(@args);
|
||||
for (my $num = 0; $num < $len; $num++) {
|
||||
print ", " if $num > 0;
|
||||
my $arg = $args[$num];
|
||||
if ($arg =~ /([^]]+)(\[[^]]\])/) {
|
||||
my $argtype = $1;
|
||||
my $array = $2;
|
||||
printf("%s arg%d%s", $argtype, $num, $array);
|
||||
} else {
|
||||
if ($arg eq "void") {
|
||||
printf("void");
|
||||
} else {
|
||||
printf("%s arg%d", $arg, $num);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(") {\n");
|
||||
if ($type eq "void") {
|
||||
printf(" CALL_GL_API(%s", $name);
|
||||
} else {
|
||||
printf(" CALL_GL_API_RETURN(%s", $name);
|
||||
}
|
||||
for (my $num = 0; $num < $len; $num++) {
|
||||
if ($args[$num] ne "void") {
|
||||
print ", ";
|
||||
printf("arg%d", $num);
|
||||
}
|
||||
}
|
||||
printf(");\n}\n\n");
|
||||
}
|
||||
18
opengl/tests/copybits/Android.mk
Normal file
18
opengl/tests/copybits/Android.mk
Normal file
@@ -0,0 +1,18 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
copybits.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
libEGL \
|
||||
libGLESv1_CM \
|
||||
libui
|
||||
|
||||
LOCAL_MODULE:= test-opengl-copybits
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
752
opengl/tests/copybits/copybits.cpp
Normal file
752
opengl/tests/copybits/copybits.cpp
Normal file
@@ -0,0 +1,752 @@
|
||||
// Test software OpenGL hardware accelleration using copybits.
|
||||
|
||||
#define LOG_TAG "copybits_test"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/native_handle.h>
|
||||
|
||||
#include <utils/Atomic.h>
|
||||
|
||||
#include <private/ui/SharedState.h>
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
#include <hardware/hardware.h>
|
||||
|
||||
#define EGL_EGLEXT_PROTOTYPES
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
extern "C" EGLNativeWindowType android_createDisplaySurface(void);
|
||||
|
||||
using namespace android;
|
||||
|
||||
EGLDisplay eglDisplay;
|
||||
EGLSurface eglSurface;
|
||||
EGLContext eglContext;
|
||||
GLuint texture;
|
||||
|
||||
hw_module_t const* gralloc_module;
|
||||
alloc_device_t *sAllocDev;
|
||||
|
||||
#define FIXED_ONE 0x10000
|
||||
|
||||
int init_gl_surface();
|
||||
void free_gl_surface();
|
||||
void init_scene();
|
||||
|
||||
int create_physical_texture();
|
||||
int readTimer();
|
||||
|
||||
// ===========================================================================
|
||||
// Buffer and implementation of android_native_buffer_t
|
||||
// ===========================================================================
|
||||
|
||||
class NativeBuffer;
|
||||
|
||||
class Buffer : public android_native_buffer_t,
|
||||
public LightRefBase<Buffer>
|
||||
{
|
||||
public:
|
||||
|
||||
// creates w * h buffer
|
||||
Buffer(uint32_t w, uint32_t h, PixelFormat format, int usage);
|
||||
|
||||
// return status
|
||||
status_t initCheck() const;
|
||||
|
||||
|
||||
uint32_t getWidth() const { return mWidth; }
|
||||
uint32_t getHeight() const { return mHeight; }
|
||||
uint32_t getStride() const { return mStride; }
|
||||
uint32_t getUsage() const { return mUsage; }
|
||||
PixelFormat getPixelFormat() const { return mFormat; }
|
||||
buffer_handle_t getHandle() const { return mBufferHandle; }
|
||||
|
||||
android_native_buffer_t* getNativeBuffer() const;
|
||||
|
||||
void setPixel(int x, int y, int r, int g, int b, int a);
|
||||
|
||||
private:
|
||||
friend class LightRefBase<Buffer>;
|
||||
Buffer(const Buffer& rhs);
|
||||
~Buffer();
|
||||
Buffer& operator = (const Buffer& rhs);
|
||||
const Buffer& operator = (const Buffer& rhs) const;
|
||||
|
||||
status_t initSize(uint32_t w, uint32_t h);
|
||||
|
||||
static void incRef(android_native_base_t* buffer);
|
||||
static void decRef(android_native_base_t* buffer);
|
||||
static int getHandlePriv(android_native_buffer_t const * buffer,
|
||||
buffer_handle_t* handle);
|
||||
|
||||
buffer_handle_t mBufferHandle;
|
||||
ssize_t mInitCheck;
|
||||
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mStride;
|
||||
uint32_t mVStride;
|
||||
PixelFormat mFormat;
|
||||
void* mData;
|
||||
uint32_t mUsage;
|
||||
};
|
||||
|
||||
Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, int usage)
|
||||
: mBufferHandle(0), mInitCheck(NO_INIT),
|
||||
mWidth(0), mHeight(0), mStride(0), mVStride(0), mFormat(format), mData(0),
|
||||
mUsage(usage)
|
||||
{
|
||||
common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
|
||||
common.version = sizeof(android_native_buffer_t);
|
||||
common.incRef = incRef;
|
||||
common.decRef = decRef;
|
||||
android_native_buffer_t::getHandle = getHandlePriv;
|
||||
if (w>0 && h>0) {
|
||||
mInitCheck = initSize(w, h);
|
||||
}
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
if (mBufferHandle) {
|
||||
|
||||
gralloc_module_t* mod = (gralloc_module_t*)sAllocDev->common.module;
|
||||
mod->unmap(mod, mBufferHandle);
|
||||
|
||||
sAllocDev->free(sAllocDev, mBufferHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::incRef(android_native_base_t* buffer) {
|
||||
Buffer* self = static_cast<Buffer*>(
|
||||
reinterpret_cast<android_native_buffer_t *>(buffer));
|
||||
self->incStrong(self);
|
||||
}
|
||||
|
||||
void Buffer::decRef(android_native_base_t* buffer) {
|
||||
Buffer* self = static_cast<Buffer*>(
|
||||
reinterpret_cast<android_native_buffer_t *>(buffer));
|
||||
self->decStrong(self);
|
||||
}
|
||||
|
||||
int Buffer::getHandlePriv(android_native_buffer_t const * buffer,
|
||||
buffer_handle_t* handle) {
|
||||
Buffer const * self = static_cast<Buffer const *>(buffer);
|
||||
*handle = self->getHandle();
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t Buffer::initCheck() const {
|
||||
return mInitCheck;
|
||||
}
|
||||
|
||||
android_native_buffer_t* Buffer::getNativeBuffer() const
|
||||
{
|
||||
Buffer* that = const_cast<Buffer*>(this);
|
||||
that->android_native_buffer_t::width = mWidth;
|
||||
that->android_native_buffer_t::height = mHeight;
|
||||
that->android_native_buffer_t::stride = mStride;
|
||||
that->android_native_buffer_t::format = mFormat;
|
||||
that->android_native_buffer_t::usage = mUsage;
|
||||
that->android_native_buffer_t::bits = mData;
|
||||
return static_cast<android_native_buffer_t*>(that);
|
||||
}
|
||||
|
||||
status_t Buffer::initSize(uint32_t w, uint32_t h)
|
||||
{
|
||||
status_t err = NO_ERROR;
|
||||
|
||||
int32_t stride;
|
||||
err = sAllocDev->alloc(sAllocDev, w, h, mFormat, mUsage, &mBufferHandle, &stride);
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
void* addr = 0;
|
||||
gralloc_module_t* mod = (gralloc_module_t*)sAllocDev->common.module;
|
||||
err = mod->map(mod, mBufferHandle, &addr);
|
||||
if (err == NO_ERROR) {
|
||||
mData = addr;
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
mStride = stride;
|
||||
mVStride = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void Buffer::setPixel(int x, int y, int r, int g, int b, int a) {
|
||||
if (x < 0 || (unsigned int) x >= mWidth
|
||||
|| y < 0 || (unsigned int) y >= mHeight) {
|
||||
// clipped
|
||||
return;
|
||||
}
|
||||
int index = mStride * y + x;
|
||||
switch (mFormat) {
|
||||
case HAL_PIXEL_FORMAT_RGB_565: {
|
||||
unsigned short val = (unsigned short) (
|
||||
((0x1f & (r >> 3)) << 11)
|
||||
| ((0x3f & (g >> 2)) << 5)
|
||||
| (0x1f & (b >> 3)));
|
||||
((unsigned short*) mData)[index]= val;
|
||||
}
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_RGBA_8888: { // ABGR
|
||||
unsigned int val = (unsigned int)
|
||||
(((a & 0xff) << 24)
|
||||
| ((b & 0xff) << 16)
|
||||
| ((g & 0xff) << 8)
|
||||
| (r & 0xff));
|
||||
((unsigned int*) mData)[index] = val;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Unsupported pixel format
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void gluLookAt(float eyeX, float eyeY, float eyeZ,
|
||||
float centerX, float centerY, float centerZ, float upX, float upY,
|
||||
float upZ)
|
||||
{
|
||||
// See the OpenGL GLUT documentation for gluLookAt for a description
|
||||
// of the algorithm. We implement it in a straightforward way:
|
||||
|
||||
float fx = centerX - eyeX;
|
||||
float fy = centerY - eyeY;
|
||||
float fz = centerZ - eyeZ;
|
||||
|
||||
// Normalize f
|
||||
float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz);
|
||||
fx *= rlf;
|
||||
fy *= rlf;
|
||||
fz *= rlf;
|
||||
|
||||
// Normalize up
|
||||
float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ);
|
||||
upX *= rlup;
|
||||
upY *= rlup;
|
||||
upZ *= rlup;
|
||||
|
||||
// compute s = f x up (x means "cross product")
|
||||
|
||||
float sx = fy * upZ - fz * upY;
|
||||
float sy = fz * upX - fx * upZ;
|
||||
float sz = fx * upY - fy * upX;
|
||||
|
||||
// compute u = s x f
|
||||
float ux = sy * fz - sz * fy;
|
||||
float uy = sz * fx - sx * fz;
|
||||
float uz = sx * fy - sy * fx;
|
||||
|
||||
float m[16] ;
|
||||
m[0] = sx;
|
||||
m[1] = ux;
|
||||
m[2] = -fx;
|
||||
m[3] = 0.0f;
|
||||
|
||||
m[4] = sy;
|
||||
m[5] = uy;
|
||||
m[6] = -fy;
|
||||
m[7] = 0.0f;
|
||||
|
||||
m[8] = sz;
|
||||
m[9] = uz;
|
||||
m[10] = -fz;
|
||||
m[11] = 0.0f;
|
||||
|
||||
m[12] = 0.0f;
|
||||
m[13] = 0.0f;
|
||||
m[14] = 0.0f;
|
||||
m[15] = 1.0f;
|
||||
|
||||
glMultMatrixf(m);
|
||||
glTranslatef(-eyeX, -eyeY, -eyeZ);
|
||||
}
|
||||
|
||||
int init_gralloc() {
|
||||
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gralloc_module);
|
||||
LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
|
||||
|
||||
if (err == 0) {
|
||||
gralloc_open(gralloc_module, &sAllocDev);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int init_gl_surface(void)
|
||||
{
|
||||
EGLint numConfigs = 1;
|
||||
EGLConfig myConfig = {0};
|
||||
EGLint attrib[] =
|
||||
{
|
||||
EGL_DEPTH_SIZE, 16,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
printf("init_gl_surface\n");
|
||||
if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY )
|
||||
{
|
||||
printf("eglGetDisplay failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE )
|
||||
{
|
||||
printf("eglInitialize failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( eglChooseConfig(eglDisplay, attrib, &myConfig, 1, &numConfigs) != EGL_TRUE )
|
||||
{
|
||||
printf("eglChooseConfig failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig,
|
||||
android_createDisplaySurface(), 0)) == EGL_NO_SURFACE )
|
||||
{
|
||||
printf("eglCreateWindowSurface failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT )
|
||||
{
|
||||
printf("eglCreateContext failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE )
|
||||
{
|
||||
printf("eglMakeCurrent failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void free_gl_surface(void)
|
||||
{
|
||||
if (eglDisplay != EGL_NO_DISPLAY)
|
||||
{
|
||||
eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE, EGL_NO_CONTEXT );
|
||||
eglDestroyContext( eglDisplay, eglContext );
|
||||
eglDestroySurface( eglDisplay, eglSurface );
|
||||
eglTerminate( eglDisplay );
|
||||
eglDisplay = EGL_NO_DISPLAY;
|
||||
}
|
||||
}
|
||||
|
||||
void init_scene(void)
|
||||
{
|
||||
glDisable(GL_DITHER);
|
||||
glEnable(GL_CULL_FACE);
|
||||
float ratio = 320.0f / 480.0f;
|
||||
glViewport(0, 0, 320, 480);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustumf(-ratio, ratio, -1, 1, 1, 10);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glLoadIdentity();
|
||||
gluLookAt(
|
||||
0, 0, 3, // eye
|
||||
0, 0, 0, // center
|
||||
0, 1, 0); // up
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
// #define USE_ALPHA_COLOR
|
||||
|
||||
#define USE_GL_REPLACE
|
||||
// #define USE_GL_MODULATE
|
||||
|
||||
// #define USE_BLEND
|
||||
|
||||
#define USE_565
|
||||
// #define USE_8888
|
||||
|
||||
// #define USE_NEAREST
|
||||
#define USE_LINEAR
|
||||
|
||||
#define USE_SCALE
|
||||
|
||||
void setSmoothGradient(Buffer* bufferObject) {
|
||||
int pixels = bufferObject->getHeight() * bufferObject->getWidth();
|
||||
int step = 0;
|
||||
for (unsigned int y = 0; y < bufferObject->getHeight(); y++) {
|
||||
for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) {
|
||||
int grey = step * 255 / pixels;
|
||||
bufferObject->setPixel(x, y, grey, grey, grey, 255);
|
||||
++step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setSmoothAlphaGradient(Buffer* bufferObject) {
|
||||
int pixels = bufferObject->getHeight() * bufferObject->getWidth();
|
||||
int step = 0;
|
||||
for (unsigned int y = 0; y < bufferObject->getHeight(); y++) {
|
||||
for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) {
|
||||
int grey = step * 255 / pixels;
|
||||
bufferObject->setPixel(x, y, 255, 255, 255, grey);
|
||||
++step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setOrientedCheckerboard(Buffer* bufferObject) {
|
||||
bufferObject->setPixel(0, 0, 0, 0, 0, 255);
|
||||
for(unsigned int x = 1; x < bufferObject->getWidth() ; x++) {
|
||||
bufferObject->setPixel(x, 0, 0, 255, 0, 255);
|
||||
}
|
||||
for (unsigned int y = 1; y < bufferObject->getHeight(); y++) {
|
||||
for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) {
|
||||
if ((x ^ y ) & 1) {
|
||||
bufferObject->setPixel(x, y, 255, 255, 255, 255);
|
||||
} else {
|
||||
bufferObject->setPixel(x, y, 255, 0, 0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int create_physical_texture(unsigned int w, unsigned int h)
|
||||
{
|
||||
|
||||
#ifdef USE_565
|
||||
PixelFormat format = HAL_PIXEL_FORMAT_RGB_565;
|
||||
#else
|
||||
PixelFormat format = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
#endif
|
||||
int usage = GRALLOC_USAGE_SW_READ_OFTEN |
|
||||
GRALLOC_USAGE_SW_WRITE_OFTEN |
|
||||
GRALLOC_USAGE_HW_TEXTURE |
|
||||
GRALLOC_USAGE_HW_2D; /* This is the key to allocating the texture in pmem. */
|
||||
int32_t stride;
|
||||
buffer_handle_t handle;
|
||||
|
||||
// Allocate the hardware buffer
|
||||
Buffer* bufferObject = new Buffer(w, h, format, usage);
|
||||
|
||||
android_native_buffer_t* buffer = bufferObject->getNativeBuffer();
|
||||
|
||||
buffer->common.incRef(&buffer->common);
|
||||
|
||||
// create the new EGLImageKHR
|
||||
EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_NONE };
|
||||
EGLDisplay dpy = eglGetCurrentDisplay();
|
||||
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
|
||||
(EGLClientBuffer)buffer, attrs);
|
||||
if (image == EGL_NO_IMAGE_KHR) {
|
||||
printf("Could not create an image %d\n", eglGetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->bits == NULL) {
|
||||
printf("No bits allocated for image.\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
setOrientedCheckerboard(bufferObject);
|
||||
// setSmoothGradient(bufferObject);
|
||||
// setSmoothAlphaGradient(bufferObject);
|
||||
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
||||
#ifdef USE_LINEAR
|
||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
#elif defined(USE_NEAREST)
|
||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
#endif
|
||||
|
||||
#ifdef USE_GL_REPLACE
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
#elif defined(USE_GL_MODULATE)
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ALPHA_COLOR
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.4f);
|
||||
#else
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLEND
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const int SCALE_COUNT = 12;
|
||||
|
||||
int scale(int base, int factor) {
|
||||
static const float kTable[SCALE_COUNT] = {
|
||||
0.1f, 0.25f, 0.5f, 0.75f, 1.0f,
|
||||
1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 5.0f
|
||||
};
|
||||
return base * kTable[factor];
|
||||
}
|
||||
|
||||
class Timer {
|
||||
struct timeval first;
|
||||
double elapsedSeconds;
|
||||
|
||||
public:
|
||||
Timer() {}
|
||||
void start() {
|
||||
gettimeofday(&first, NULL);
|
||||
}
|
||||
|
||||
void stop() {
|
||||
struct timeval second,
|
||||
elapsed;
|
||||
gettimeofday(&second, NULL);
|
||||
|
||||
if (first.tv_usec > second.tv_usec) {
|
||||
second.tv_usec += 1000000;
|
||||
second.tv_sec--;
|
||||
}
|
||||
|
||||
elapsedSeconds = (second.tv_sec - first.tv_sec) +
|
||||
(second.tv_usec - first.tv_usec) / 1000000.0;
|
||||
}
|
||||
|
||||
double getElapsedSeconds() {
|
||||
return elapsedSeconds;
|
||||
}
|
||||
|
||||
double getElapsedMs() {
|
||||
return elapsedSeconds* 1000.0f;
|
||||
}
|
||||
};
|
||||
|
||||
int testTime()
|
||||
{
|
||||
static const int WIDTH = 320;
|
||||
static const int HEIGHT = 480;
|
||||
static const int SCALE = 8;
|
||||
|
||||
if (create_physical_texture(WIDTH, HEIGHT) != 0) {
|
||||
return -1;
|
||||
}
|
||||
// Need to do a dummy eglSwapBuffers first. Don't know why.
|
||||
glClearColor(0.4, 1.0, 0.4, 0.4);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
eglSwapBuffers(eglDisplay, eglSurface);
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
#if defined(USE_SCALE)
|
||||
static const int scaleOffset = 0;
|
||||
#else
|
||||
static const int scaleOffset = 1;
|
||||
#endif
|
||||
printf("ms\n");
|
||||
for(int j = 0; j < SCALE; j++) {
|
||||
int w = WIDTH >> (j + scaleOffset);
|
||||
int h = HEIGHT >> j;
|
||||
int cropRect[4] = {0,h,w,-h}; // Left bottom width height. Width and Height can be neg to flip.
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
|
||||
Timer timer;
|
||||
timer.start();
|
||||
|
||||
int copyCount = 1000;
|
||||
for (int i = 0; i < copyCount; i++) {
|
||||
glDrawTexiOES(0, 0, 0, w, h);
|
||||
}
|
||||
|
||||
timer.stop();
|
||||
printf("%g\n", timer.getElapsedMs() / copyCount);
|
||||
}
|
||||
|
||||
eglSwapBuffers(eglDisplay, eglSurface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testStretch()
|
||||
{
|
||||
static const int WIDTH = 8;
|
||||
static const int HEIGHT = 8;
|
||||
|
||||
if (create_physical_texture(WIDTH, HEIGHT) != 0) {
|
||||
return -1;
|
||||
}
|
||||
// Need to do a dummy eglSwapBuffers first. Don't know why.
|
||||
glClearColor(0.4, 1.0, 0.4, 0.4);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
eglSwapBuffers(eglDisplay, eglSurface);
|
||||
|
||||
int cropRect[4] = {0,HEIGHT,WIDTH,-HEIGHT}; // Left bottom width height. Width and Height can be neg to flip.
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
|
||||
|
||||
for(int frame = 0; frame < 2; frame++) {
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
int baseX = 10;
|
||||
for (int x = 0; x < SCALE_COUNT; x++) {
|
||||
int baseY = 10;
|
||||
int width = scale(WIDTH, x);
|
||||
for (int y = 0; y < SCALE_COUNT; y++) {
|
||||
int height = scale(HEIGHT, y);
|
||||
glDrawTexxOES(baseX << 16, baseY << 16, 0, width << 16, height << 16);
|
||||
baseY += height + 10;
|
||||
}
|
||||
baseX += width + 10;
|
||||
}
|
||||
|
||||
eglSwapBuffers(eglDisplay, eglSurface);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testRot90()
|
||||
{
|
||||
static const int WIDTH = 8;
|
||||
static const int HEIGHT = 8;
|
||||
|
||||
if (create_physical_texture(WIDTH, HEIGHT) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrthof(0, 320, 480, 0, 0, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glLoadIdentity();
|
||||
|
||||
// Need to do a dummy eglSwapBuffers first. Don't know why.
|
||||
glClearColor(0.4, 0.4, 0.4, 0.4);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
eglSwapBuffers(eglDisplay, eglSurface);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
|
||||
glDisable(GL_BLEND);
|
||||
glShadeModel(GL_FLAT);
|
||||
glDisable(GL_DITHER);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
for(int frame = 0; frame < 2; frame++) {
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
int baseX = 10;
|
||||
for (int x = 0; x < SCALE_COUNT; x++) {
|
||||
int baseY = 10;
|
||||
int width = scale(WIDTH, x);
|
||||
for (int y = 0; y < SCALE_COUNT; y++) {
|
||||
int height = scale(HEIGHT, y);
|
||||
|
||||
// Code copied from SurfaceFlinger LayerBase.cpp
|
||||
|
||||
const GLfixed texCoords[4][2] = {
|
||||
{ 0, 0 },
|
||||
{ 0, 0x10000 },
|
||||
{ 0x10000, 0x10000 },
|
||||
{ 0x10000, 0 }
|
||||
};
|
||||
|
||||
GLfixed fx = baseX << 16;
|
||||
GLfixed fy = baseY << 16;
|
||||
GLfixed fw = width << 16;
|
||||
GLfixed fh = height << 16;
|
||||
|
||||
/*
|
||||
* Vertex pattern:
|
||||
* (2)--(3)
|
||||
* |\ |
|
||||
* | \ |
|
||||
* | \ |
|
||||
* | \|
|
||||
* (1)--(0)
|
||||
*
|
||||
*/
|
||||
|
||||
const GLfixed vertices[4][2] = {
|
||||
{fx + fw, fy},
|
||||
{fx, fy},
|
||||
{fx, fy + fh},
|
||||
{fx + fw, fy + fh}
|
||||
};
|
||||
|
||||
static const bool rotate90 = true;
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glVertexPointer(2, GL_FIXED, 0, vertices);
|
||||
glTexCoordPointer(2, GL_FIXED, 0, texCoords);
|
||||
|
||||
LOGW("testRot90 %d, %d %d, %d", baseX, baseY, width, height);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
baseY += height + 10;
|
||||
}
|
||||
baseX += width + 10;
|
||||
}
|
||||
|
||||
eglSwapBuffers(eglDisplay, eglSurface);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
int q;
|
||||
int start, end;
|
||||
|
||||
if (init_gralloc()) {
|
||||
printf("gralloc initialization failed - exiting\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Initializing EGL...\n");
|
||||
|
||||
if(!init_gl_surface())
|
||||
{
|
||||
printf("GL initialisation failed - exiting\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
init_scene();
|
||||
|
||||
printf("Start test...\n");
|
||||
// testTime();
|
||||
// testStretch();
|
||||
testRot90();
|
||||
free_gl_surface();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user