Integrate from //sandbox/mathias/donut/...@145728

SurfaceFlinger rework for new EGL driver model support.
This commit is contained in:
Mathias Agopian
2009-04-10 14:24:30 -07:00
parent 71d83c0489
commit 1473f46cbc
83 changed files with 5854 additions and 3297 deletions

View File

@@ -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 \

View File

@@ -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(

View File

@@ -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
View File

Before

Width:  |  Height:  |  Size: 898 B

After

Width:  |  Height:  |  Size: 898 B

View File

@@ -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() {

View File

@@ -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
View 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

View File

@@ -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;
};
// ---------------------------------------------------------------------------

View File

@@ -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(

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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
View 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

View File

@@ -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)

View File

@@ -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(),

View File

@@ -72,7 +72,6 @@ private:
EGLDisplay mContext;
EGLDisplay mSurface;
sp<Surface> mFlingerSurface;
sp<EGLNativeWindowSurface> mNativeWindowSurface;
Barrier mBarrier;
};

View 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

View 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

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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;
};

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
#define LOG_TAG "SurfaceFlinger"
#include <assert.h>
#include <errno.h>
#include <stdlib.h>

View File

@@ -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;
}
// ---------------------------------------------------------------------------

View File

@@ -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;
};
// ---------------------------------------------------------------------------

View File

@@ -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;
};
// ---------------------------------------------------------------------------

View File

@@ -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;
};
// ---------------------------------------------------------------------------

View File

@@ -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;
}
// ---------------------------------------------------------------------------

View File

@@ -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

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
#define LOG_TAG "SurfaceFlinger"
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>

View File

@@ -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);
}

View File

@@ -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;
};
// ---------------------------------------------------------------------------

View File

@@ -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);
}
}
}

View File

@@ -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;
};
// ---------------------------------------------------------------------------

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -72,8 +72,7 @@ private:
bool finished();
sp<SurfaceFlinger> mFlinger;
sp<MemoryDealer> mTemporaryDealer;
LayerOrientationAnimBase* mLayerOrientationAnim;
sp< LayerOrientationAnimBase > mLayerOrientationAnim;
int mState;
uint32_t mType;
};

View File

@@ -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

View File

@@ -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;

View File

@@ -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));
}
}

View 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

View 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

View 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)

View 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;
}

View File

@@ -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
View 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

View File

@@ -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
// ----------------------------------------------------------------------------

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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);
}
}
};

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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;

View 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 */

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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
View 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
View 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

View File

@@ -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;
}

View File

@@ -2,16 +2,16 @@
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
@@ -28,12 +28,16 @@
#include "BufferObjectManager.h"
#include "TextureObjectManager.h"
#ifdef LIBAGL_USE_GRALLOC_COPYBITS
#include <hardware/copybit.h>
#endif // LIBAGL_USE_GRALLOC_COPYBITS
namespace android {
// ----------------------------------------------------------------------------
static char const * const gVendorString = "Android";
static char const * const gRendererString = "Android PixelFlinger 1.0";
static char const * const gRendererString = "Android PixelFlinger 1.1";
static char const * const gVersionString = "OpenGL ES-CM 1.0";
static char const * const gExtensionsString =
"GL_OES_byte_coordinates " // OK
@@ -46,9 +50,9 @@ static char const * const gExtensionsString =
"GL_OES_query_matrix " // OK
// "GL_OES_point_size_array " // TODO
// "GL_OES_point_sprite " // TODO
"GL_OES_EGL_image " // OK
"GL_ARB_texture_compression " // OK
"GL_ARB_texture_non_power_of_two " // OK
"GL_ANDROID_direct_texture " // OK
"GL_ANDROID_user_clip_plane " // OK
"GL_ANDROID_vertex_buffer_object " // OK
"GL_ANDROID_generate_mipmap " // OK
@@ -62,13 +66,13 @@ static char const * const gExtensionsString =
ogles_context_t *ogles_init(size_t extra)
{
void* const base = malloc(extra + sizeof(ogles_context_t) + 32);
if (!base) return 0;
if (!base) return 0;
ogles_context_t *c =
(ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL);
memset(c, 0, sizeof(ogles_context_t));
ggl_init_context(&(c->rasterizer));
// XXX: this should be passed as an argument
sp<EGLSurfaceManager> smgr(new EGLSurfaceManager());
c->surfaceManager = smgr.get();
@@ -87,13 +91,42 @@ ogles_context_t *ogles_init(size_t extra)
c->rasterizer.base = base;
c->point.size = TRI_ONE;
c->line.width = TRI_ONE;
// in OpenGL, writing to the depth buffer is enabled by default.
c->rasterizer.procs.depthMask(c, 1);
// OpenGL enables dithering by default
c->rasterizer.procs.enable(c, GL_DITHER);
c->copybits.blitEngine = NULL;
c->copybits.minScale = 0;
c->copybits.maxScale = 0;
c->copybits.drawSurfaceFd = -1;
#ifdef LIBAGL_USE_GRALLOC_COPYBITS
hw_module_t const* module;
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
struct copybit_device_t* copyBits;
if (copybit_open(module, &copyBits) == 0) {
c->copybits.blitEngine = copyBits;
{
int minLim = copyBits->get(copyBits,
COPYBIT_MINIFICATION_LIMIT);
if (minLim != -EINVAL && minLim > 0) {
c->copybits.minScale = (1 << 16) / minLim;
}
}
{
int magLim = copyBits->get(copyBits,
COPYBIT_MAGNIFICATION_LIMIT);
if (magLim != -EINVAL && magLim > 0) {
c->copybits.maxScale = min(32*1024-1, magLim) << 16;
}
}
}
}
#endif // LIBAGL_USE_GRALLOC_COPYBITS
return c;
}
@@ -107,7 +140,12 @@ void ogles_uninit(ogles_context_t* c)
c->surfaceManager->decStrong(c);
c->bufferObjectManager->decStrong(c);
ggl_uninit_context(&(c->rasterizer));
free(c->rasterizer.base);
free(c->rasterizer.base);
#ifdef LIBAGL_USE_GRALLOC_COPYBITS
if (c->copybits.blitEngine != NULL) {
copybit_close((struct copybit_device_t*) c->copybits.blitEngine);
}
#endif // LIBAGL_USE_GRALLOC_COPYBITS
}
void _ogles_error(ogles_context_t* c, GLenum error)
@@ -188,7 +226,7 @@ static void enable_disable(ogles_context_t* c, GLenum cap, int enabled)
// these need to fall through into the rasterizer
c->rasterizer.procs.enableDisable(c, cap, enabled);
break;
case GL_MULTISAMPLE:
case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_ALPHA_TO_ONE:
@@ -281,7 +319,7 @@ void glHint(GLenum target, GLenum mode)
case GL_LINE_SMOOTH_HINT:
break;
case GL_POINT_SMOOTH_HINT:
c->rasterizer.procs.enableDisable(c,
c->rasterizer.procs.enableDisable(c,
GGL_POINT_SMOOTH_NICE, mode==GL_NICEST);
break;
case GL_PERSPECTIVE_CORRECTION_HINT:
@@ -323,7 +361,7 @@ GLenum glGetError()
c->error = 0;
return ret;
}
if (c->rasterizer.error) {
const GLenum ret(c->rasterizer.error);
c->rasterizer.error = 0;
@@ -362,25 +400,25 @@ void glGetIntegerv(GLenum pname, GLint *params)
int index = c->rasterizer.state.buffers.color.format;
GGLFormat const * formats = gglGetPixelFormatTable();
params[0] = formats[index].ah - formats[index].al;
break;
break;
}
case GL_RED_BITS: {
int index = c->rasterizer.state.buffers.color.format;
GGLFormat const * formats = gglGetPixelFormatTable();
params[0] = formats[index].rh - formats[index].rl;
break;
break;
}
case GL_GREEN_BITS: {
int index = c->rasterizer.state.buffers.color.format;
GGLFormat const * formats = gglGetPixelFormatTable();
params[0] = formats[index].gh - formats[index].gl;
break;
break;
}
case GL_BLUE_BITS: {
int index = c->rasterizer.state.buffers.color.format;
GGLFormat const * formats = gglGetPixelFormatTable();
params[0] = formats[index].bh - formats[index].bl;
break;
break;
}
case GL_COMPRESSED_TEXTURE_FORMATS:
params[ 0] = GL_PALETTE4_RGB8_OES;

View File

@@ -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)
{
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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
// ----------------------------------------------------------------------------

View File

@@ -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 *)

View File

@@ -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
View 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");
}

View 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)

View 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;
}