update surfaceflinger, libui and libagl to the new gralloc api
- Currently the lock/unlock path is naive and is done for each drawing operation (glDrawElements and glDrawArrays). this should be improved eventually. - factor all the lock/unlock code in SurfaceBuffer. - fixed "showupdate" so it works even when we don't have preserving eglSwapBuffers(). - improved the situation with the dirty-region and fixed a problem that caused GL apps to not update. - make use of LightRefBase() where needed, instead of duplicating its implementation - add LightRefBase::getStrongCount() - renamed EGLNativeWindowSurface.cpp to FramebufferNativeWindow.cpp - disabled copybits test, since it clashes with the new gralloc api - Camera/Video will be fixed later when we rework the overlay apis
This commit is contained in:
@@ -20,10 +20,7 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/CallStack.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Singleton.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
@@ -40,9 +37,14 @@ class BufferMapper : public Singleton<BufferMapper>
|
||||
{
|
||||
public:
|
||||
static inline BufferMapper& get() { return getInstance(); }
|
||||
status_t map(buffer_handle_t handle, void** addr, const void* id);
|
||||
status_t unmap(buffer_handle_t handle, const void* id);
|
||||
status_t lock(buffer_handle_t handle, int usage, const Rect& bounds);
|
||||
|
||||
status_t registerBuffer(buffer_handle_t handle);
|
||||
|
||||
status_t unregisterBuffer(buffer_handle_t handle);
|
||||
|
||||
status_t lock(buffer_handle_t handle,
|
||||
int usage, const Rect& bounds, void** vaddr);
|
||||
|
||||
status_t unlock(buffer_handle_t handle);
|
||||
|
||||
// dumps information about the mapping of this handle
|
||||
@@ -51,16 +53,7 @@ public:
|
||||
private:
|
||||
friend class Singleton<BufferMapper>;
|
||||
BufferMapper();
|
||||
mutable Mutex mLock;
|
||||
gralloc_module_t const *mAllocMod;
|
||||
|
||||
void logMapLocked(buffer_handle_t handle, const void* id);
|
||||
void logUnmapLocked(buffer_handle_t handle, const void* id);
|
||||
struct map_info_t {
|
||||
const void* id;
|
||||
CallStack stack;
|
||||
};
|
||||
KeyedVector<buffer_handle_t, Vector<map_info_t> > mMapInfo;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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_EGL_DISPLAY_SURFACE_H
|
||||
#define ANDROID_EGL_DISPLAY_SURFACE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Timers.h>
|
||||
|
||||
#include <ui/EGLNativeSurface.h>
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
struct copybit_device_t;
|
||||
struct copybit_image_t;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Region;
|
||||
class Rect;
|
||||
|
||||
class EGLDisplaySurface : public EGLNativeSurface<EGLDisplaySurface>
|
||||
{
|
||||
public:
|
||||
EGLDisplaySurface();
|
||||
~EGLDisplaySurface();
|
||||
|
||||
int32_t getPageFlipCount() const;
|
||||
void copyFrontToBack(const Region& copyback);
|
||||
void copyFrontToImage(const copybit_image_t& dst);
|
||||
void copyBackToImage(const copybit_image_t& dst);
|
||||
|
||||
void setSwapRectangle(int l, int t, int w, int h);
|
||||
|
||||
private:
|
||||
static void hook_incRef(NativeWindowType window);
|
||||
static void hook_decRef(NativeWindowType window);
|
||||
static uint32_t hook_swapBuffers(NativeWindowType window);
|
||||
|
||||
uint32_t swapBuffers();
|
||||
|
||||
status_t mapFrameBuffer();
|
||||
|
||||
enum {
|
||||
PAGE_FLIP = 0x00000001
|
||||
};
|
||||
GGLSurface mFb[2];
|
||||
int mIndex;
|
||||
uint32_t mFlags;
|
||||
size_t mSize;
|
||||
fb_var_screeninfo mInfo;
|
||||
fb_fix_screeninfo mFinfo;
|
||||
int32_t mPageFlipCount;
|
||||
nsecs_t mTime;
|
||||
int32_t mSwapCount;
|
||||
nsecs_t mSleep;
|
||||
uint32_t mFeatureFlags;
|
||||
copybit_device_t* mBlitEngine;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_EGL_DISPLAY_SURFACE_H
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
|
||||
#define ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
|
||||
#ifndef ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
|
||||
#define ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
@@ -76,32 +76,18 @@ public:
|
||||
|
||||
framebuffer_device_t const * getDevice() const { return fbDev; }
|
||||
|
||||
void setSwapRectangle(const Rect& dirty);
|
||||
|
||||
private:
|
||||
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);
|
||||
|
||||
|
||||
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;
|
||||
|
||||
@@ -121,5 +107,5 @@ private:
|
||||
}; // namespace android
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
|
||||
#endif // ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
|
||||
void clear();
|
||||
void set(const Rect& r);
|
||||
void set(uint32_t w, uint32_t h);
|
||||
|
||||
Region& orSelf(const Rect& rhs);
|
||||
Region& andSelf(const Rect& rhs);
|
||||
|
||||
@@ -34,7 +34,9 @@ namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class BufferMapper;
|
||||
class Rect;
|
||||
class Surface;
|
||||
class SurfaceComposerClient;
|
||||
struct per_client_cblk_t;
|
||||
struct layer_cblk_t;
|
||||
@@ -52,6 +54,10 @@ public:
|
||||
return handle;
|
||||
}
|
||||
|
||||
status_t lock(uint32_t usage);
|
||||
status_t lock(uint32_t usage, const Rect& rect);
|
||||
status_t unlock();
|
||||
|
||||
protected:
|
||||
SurfaceBuffer();
|
||||
SurfaceBuffer(const Parcel& reply);
|
||||
@@ -59,7 +65,11 @@ protected:
|
||||
buffer_handle_t handle;
|
||||
bool mOwner;
|
||||
|
||||
inline const BufferMapper& getBufferMapper() const { return mBufferMapper; }
|
||||
inline BufferMapper& getBufferMapper() { return mBufferMapper; }
|
||||
|
||||
private:
|
||||
friend class Surface;
|
||||
friend class BpSurface;
|
||||
friend class BnSurface;
|
||||
friend class LightRefBase<SurfaceBuffer>;
|
||||
@@ -72,6 +82,8 @@ private:
|
||||
|
||||
static int getHandle(android_native_buffer_t const * base,
|
||||
buffer_handle_t* handle);
|
||||
|
||||
BufferMapper& mBufferMapper;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -191,9 +203,8 @@ public:
|
||||
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
|
||||
status_t unlockAndPost();
|
||||
|
||||
// setSwapRectangle() is mainly used by EGL
|
||||
// setSwapRectangle() is intended to be used by GL ES clients
|
||||
void setSwapRectangle(const Rect& r);
|
||||
const Rect& swapRectangle() const;
|
||||
|
||||
private:
|
||||
// can't be copied
|
||||
@@ -216,22 +227,14 @@ private:
|
||||
const sp<ISurface>& getISurface() const { return mSurface; }
|
||||
|
||||
status_t getBufferLocked(int index);
|
||||
|
||||
|
||||
|
||||
Region dirtyRegion() const;
|
||||
void setDirtyRegion(const Region& region) const;
|
||||
|
||||
|
||||
status_t validate(per_client_cblk_t const* cblk) const;
|
||||
static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty);
|
||||
|
||||
inline const BufferMapper& getBufferMapper() const { return mBufferMapper; }
|
||||
inline BufferMapper& getBufferMapper() { return mBufferMapper; }
|
||||
|
||||
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);
|
||||
@@ -239,21 +242,27 @@ private:
|
||||
int dequeueBuffer(android_native_buffer_t** buffer);
|
||||
int lockBuffer(android_native_buffer_t* buffer);
|
||||
int queueBuffer(android_native_buffer_t* buffer);
|
||||
|
||||
|
||||
status_t dequeueBuffer(sp<SurfaceBuffer>* buffer);
|
||||
status_t lockBuffer(const sp<SurfaceBuffer>& buffer);
|
||||
status_t queueBuffer(const sp<SurfaceBuffer>& buffer);
|
||||
|
||||
|
||||
alloc_device_t* mAllocDevice;
|
||||
sp<SurfaceComposerClient> mClient;
|
||||
sp<ISurface> mSurface;
|
||||
sp<SurfaceBuffer> mBuffers[2];
|
||||
android_native_buffer_t* mLockedBuffer;
|
||||
sp<SurfaceBuffer> mLockedBuffer;
|
||||
SurfaceID mToken;
|
||||
uint32_t mIdentity;
|
||||
PixelFormat mFormat;
|
||||
uint32_t mFlags;
|
||||
mutable Region mDirtyRegion;
|
||||
mutable Rect mSwapRectangle;
|
||||
mutable Region mOldDirtyRegion;
|
||||
mutable uint8_t mBackbufferIndex;
|
||||
mutable Mutex mSurfaceLock;
|
||||
Rect mSwapRectangle;
|
||||
BufferMapper& mBufferMapper;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -156,6 +156,10 @@ public:
|
||||
delete static_cast<const T*>(this);
|
||||
}
|
||||
}
|
||||
//! DEBUGGING ONLY: Get current strong ref count.
|
||||
inline int32_t getStrongCount() const {
|
||||
return mCount;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline ~LightRefBase() { }
|
||||
|
||||
@@ -14,10 +14,7 @@ LOCAL_SRC_FILES:= \
|
||||
LayerBlur.cpp \
|
||||
LayerBitmap.cpp \
|
||||
LayerDim.cpp \
|
||||
LayerOrientationAnim.cpp \
|
||||
LayerOrientationAnimRotate.cpp \
|
||||
MessageQueue.cpp \
|
||||
OrientationAnimation.cpp \
|
||||
SurfaceFlinger.cpp \
|
||||
Tokenizer.cpp \
|
||||
Transform.cpp
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/ISurfaceComposer.h>
|
||||
#include <ui/ISurfaceFlingerClient.h>
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
#include <ui/FramebufferNativeWindow.h>
|
||||
|
||||
#include <core/SkBitmap.h>
|
||||
#include <images/SkImageDecoder.h>
|
||||
|
||||
@@ -16,20 +16,14 @@
|
||||
*/
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <utils/CallStack.h>
|
||||
#include <cutils/ashmem.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <utils/Singleton.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 {
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -67,8 +61,8 @@ void BufferAllocator::dump(String8& result) const
|
||||
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,
|
||||
snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u x %4u | %2d | 0x%08x\n",
|
||||
list.keyAt(i), rec.size/1024.0f,
|
||||
rec.w, rec.h, rec.format, rec.usage);
|
||||
result.append(buffer);
|
||||
total += rec.size;
|
||||
@@ -108,23 +102,9 @@ status_t BufferAllocator::free(buffer_handle_t handle)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
|
||||
#if ANDROID_GRALLOC_DEBUG
|
||||
void* base = (void*)(handle->data[2]);
|
||||
#endif
|
||||
|
||||
status_t err = mAllocDev->free(mAllocDev, handle);
|
||||
LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
|
||||
|
||||
#if ANDROID_GRALLOC_DEBUG
|
||||
if (base) {
|
||||
LOGD("freeing mapped handle %p from:", handle);
|
||||
CallStack s;
|
||||
s.update();
|
||||
s.dump("");
|
||||
BufferMapper::get().dump(handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
Mutex::Autolock _l(sLock);
|
||||
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
|
||||
@@ -134,37 +114,5 @@ status_t BufferAllocator::free(buffer_handle_t 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, this);
|
||||
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 = BufferMapper::get().unmap(handle, this);
|
||||
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
|
||||
|
||||
@@ -67,10 +67,6 @@ public:
|
||||
|
||||
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:
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
#include <ui/FramebufferNativeWindow.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <EGL/egl.h>
|
||||
@@ -313,8 +313,7 @@ void DisplayHardware::flip(const Region& dirty) const
|
||||
}
|
||||
|
||||
const Rect& b(newDirty.bounds());
|
||||
mNativeWindow->android_native_window_t::setSwapRectangle(
|
||||
mNativeWindow.get(), b.left, b.top, b.width(), b.height());
|
||||
mNativeWindow->setSwapRectangle(b);
|
||||
|
||||
mPageFlipCount++;
|
||||
eglSwapBuffers(dpy, surface);
|
||||
|
||||
@@ -69,8 +69,6 @@ void Layer::destroy()
|
||||
{
|
||||
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.
|
||||
glDeleteTextures(1, &mTextures[i].name);
|
||||
mTextures[i].name = -1U;
|
||||
}
|
||||
@@ -142,8 +140,8 @@ status_t Layer::setBuffers( Client* client,
|
||||
|
||||
void Layer::reloadTexture(const Region& dirty)
|
||||
{
|
||||
const sp<const Buffer>& buffer(frontBuffer().getBuffer());
|
||||
if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) {
|
||||
const sp<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);
|
||||
@@ -197,12 +195,16 @@ void Layer::reloadTexture(const Region& dirty)
|
||||
}
|
||||
} else {
|
||||
GGLSurface t;
|
||||
if (LIKELY(buffer->getBitmapSurface(&t) == NO_ERROR)) {
|
||||
status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY);
|
||||
LOGE_IF(res, "error %d (%s) locking buffer %p",
|
||||
res, strerror(res), buffer.get());
|
||||
if (res == NO_ERROR) {
|
||||
if (UNLIKELY(mTextures[0].name == -1U)) {
|
||||
mTextures[0].name = createTexture();
|
||||
}
|
||||
loadTexture(dirty, mTextures[0].name, t,
|
||||
mTextures[0].width, mTextures[0].height);
|
||||
buffer->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,8 +227,7 @@ void Layer::onDraw(const Region& clip) const
|
||||
|
||||
GGLSurface t;
|
||||
sp<const Buffer> buffer(frontBuffer().getBuffer());
|
||||
buffer->getBitmapSurface(&t);
|
||||
drawWithOpenGL(clip, textureName, t);
|
||||
drawWithOpenGL(clip, textureName, buffer);
|
||||
}
|
||||
|
||||
sp<SurfaceBuffer> Layer::peekBuffer()
|
||||
|
||||
@@ -377,12 +377,14 @@ void LayerBase::clearWithOpenGL(const Region& clip) const
|
||||
}
|
||||
|
||||
void LayerBase::drawWithOpenGL(const Region& clip,
|
||||
GLint textureName, const GGLSurface& t, int transform) const
|
||||
GLint textureName, const sp<const Buffer>& buffer, int transform) const
|
||||
{
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
const uint32_t fbHeight = hw.getHeight();
|
||||
const State& s(drawingState());
|
||||
|
||||
const uint32_t width = buffer->width;
|
||||
const uint32_t height = buffer->height;
|
||||
|
||||
// bind our texture
|
||||
validateTexture(textureName);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
@@ -457,14 +459,14 @@ void LayerBase::drawWithOpenGL(const Region& clip,
|
||||
|
||||
if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
|
||||
// find the smallest power-of-two that will accommodate our surface
|
||||
GLuint tw = 1 << (31 - clz(t.width));
|
||||
GLuint th = 1 << (31 - clz(t.height));
|
||||
if (tw < t.width) tw <<= 1;
|
||||
if (th < t.height) th <<= 1;
|
||||
GLuint tw = 1 << (31 - clz(width));
|
||||
GLuint th = 1 << (31 - clz(height));
|
||||
if (tw < width) tw <<= 1;
|
||||
if (th < height) th <<= 1;
|
||||
// this divide should be relatively fast because it's
|
||||
// a power-of-two (optimized path in libgcc)
|
||||
GLfloat ws = GLfloat(t.width) /tw;
|
||||
GLfloat hs = GLfloat(t.height)/th;
|
||||
GLfloat ws = GLfloat(width) /tw;
|
||||
GLfloat hs = GLfloat(height)/th;
|
||||
glScalef(ws, hs, 1.0f);
|
||||
}
|
||||
|
||||
@@ -489,15 +491,15 @@ void LayerBase::drawWithOpenGL(const Region& clip,
|
||||
Region::iterator iterator(clip);
|
||||
if (iterator) {
|
||||
Rect r;
|
||||
GLint crop[4] = { 0, t.height, t.width, -t.height };
|
||||
GLint crop[4] = { 0, height, width, -height };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
|
||||
int x = tx();
|
||||
int y = ty();
|
||||
y = fbHeight - (y + t.height);
|
||||
y = fbHeight - (y + height);
|
||||
while (iterator.iterate(&r)) {
|
||||
const GLint sy = fbHeight - (r.top + r.height());
|
||||
glScissor(r.left, sy, r.width(), r.height());
|
||||
glDrawTexiOES(x, y, 0, t.width, t.height);
|
||||
glDrawTexiOES(x, y, 0, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ class DisplayHardware;
|
||||
class GraphicPlane;
|
||||
class Client;
|
||||
class SurfaceBuffer;
|
||||
class Buffer;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -239,7 +240,7 @@ protected:
|
||||
|
||||
void drawWithOpenGL(const Region& clip,
|
||||
GLint textureName,
|
||||
const GGLSurface& surface,
|
||||
const sp<const Buffer>& buffer,
|
||||
int transform = 0) const;
|
||||
|
||||
void clearWithOpenGL(const Region& clip) const;
|
||||
|
||||
@@ -52,10 +52,7 @@ Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
if (handle) {
|
||||
BufferAllocator& allocator = BufferAllocator::get();
|
||||
if (usage & BufferAllocator::USAGE_SW_READ_MASK) {
|
||||
allocator.unmap(handle);
|
||||
}
|
||||
BufferAllocator& allocator(BufferAllocator::get());
|
||||
allocator.free(handle);
|
||||
}
|
||||
}
|
||||
@@ -107,9 +104,6 @@ status_t Buffer::initSize(uint32_t w, uint32_t h)
|
||||
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;
|
||||
@@ -120,31 +114,22 @@ status_t Buffer::initSize(uint32_t w, uint32_t h)
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t Buffer::getBitmapSurface(copybit_image_t* img) const
|
||||
status_t Buffer::lock(GGLSurface* sur, uint32_t usage)
|
||||
{
|
||||
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 res = SurfaceBuffer::lock(usage);
|
||||
if (res == NO_ERROR && sur) {
|
||||
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 res;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -73,9 +73,8 @@ public:
|
||||
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;
|
||||
|
||||
status_t lock(GGLSurface* surface, uint32_t usage);
|
||||
|
||||
android_native_buffer_t* getNativeBuffer() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -380,37 +380,37 @@ bool LayerBuffer::BufferSource::transformed() const
|
||||
|
||||
void LayerBuffer::BufferSource::onDraw(const Region& clip) const
|
||||
{
|
||||
sp<Buffer> buffer(getBuffer());
|
||||
// FIXME: we should get a native buffer here
|
||||
/*
|
||||
sp<Buffer> ourBbuffer(getBuffer());
|
||||
if (UNLIKELY(buffer == 0)) {
|
||||
// nothing to do, we don't have a buffer
|
||||
mLayer.clearWithOpenGL(clip);
|
||||
return;
|
||||
}
|
||||
|
||||
status_t err = NO_ERROR;
|
||||
NativeBuffer src(buffer->getBuffer());
|
||||
const Rect& transformedBounds = mLayer.getTransformedBounds();
|
||||
|
||||
// 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));
|
||||
|
||||
// FIXME: Use EGLImage extension for this
|
||||
mLayer.loadTexture(dirty, mTextureName, t, w, h);
|
||||
mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
|
||||
|
||||
|
||||
|
||||
GGLSurface t;
|
||||
status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY);
|
||||
if (res == NO_ERROR) {
|
||||
GLuint w = 0;
|
||||
GLuint h = 0;
|
||||
const Region dirty(Rect(buffer->width, buffer->height));
|
||||
mLayer.loadTexture(dirty, mTextureName, t, w, h);
|
||||
buffer->unlock();
|
||||
}
|
||||
if (res == NO_ERROR) {
|
||||
mLayer.drawWithOpenGL(clip, mTextureName, buffer, mBufferHeap.transform);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,8 +50,6 @@
|
||||
#include "LayerBuffer.h"
|
||||
#include "LayerDim.h"
|
||||
#include "LayerBitmap.h"
|
||||
#include "LayerOrientationAnim.h"
|
||||
#include "OrientationAnimation.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
@@ -206,7 +204,6 @@ void SurfaceFlinger::init()
|
||||
SurfaceFlinger::~SurfaceFlinger()
|
||||
{
|
||||
glDeleteTextures(1, &mWormholeTexName);
|
||||
delete mOrientationAnimation;
|
||||
}
|
||||
|
||||
overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
|
||||
@@ -399,8 +396,6 @@ status_t SurfaceFlinger::readyToRun()
|
||||
* We're now ready to accept clients...
|
||||
*/
|
||||
|
||||
mOrientationAnimation = new OrientationAnimation(this);
|
||||
|
||||
// the boot animation!
|
||||
if (mDebugNoBootAnimation == false)
|
||||
mBootAnimation = new BootAnimation(this);
|
||||
@@ -513,16 +508,17 @@ bool SurfaceFlinger::threadLoop()
|
||||
|
||||
void SurfaceFlinger::postFramebuffer()
|
||||
{
|
||||
const bool skip = mOrientationAnimation->run();
|
||||
if (UNLIKELY(skip)) {
|
||||
if (isFrozen()) {
|
||||
// we are not allowed to draw, but pause a bit to make sure
|
||||
// apps don't end up using the whole CPU, if they depend on
|
||||
// surfaceflinger for synchronization.
|
||||
usleep(8333); // 8.3ms ~ 120fps
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mInvalidRegion.isEmpty()) {
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
|
||||
hw.flip(mInvalidRegion);
|
||||
|
||||
mInvalidRegion.clear();
|
||||
}
|
||||
}
|
||||
@@ -616,7 +612,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
||||
mVisibleRegionsDirty = true;
|
||||
mDirtyRegion.set(hw.bounds());
|
||||
mFreezeDisplayTime = 0;
|
||||
mOrientationAnimation->onOrientationChanged(type);
|
||||
}
|
||||
|
||||
if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
|
||||
@@ -893,19 +888,26 @@ void SurfaceFlinger::executeScheduledBroadcasts()
|
||||
|
||||
void SurfaceFlinger::debugFlashRegions()
|
||||
{
|
||||
if (UNLIKELY(!mDirtyRegion.isRect())) {
|
||||
// TODO: do this only if we don't have preserving
|
||||
// swapBuffer. If we don't have update-on-demand,
|
||||
// redraw everything.
|
||||
composeSurfaces(Region(mDirtyRegion.bounds()));
|
||||
}
|
||||
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
const uint32_t flags = hw.getFlags();
|
||||
if (!(flags & DisplayHardware::BUFFER_PRESERVED)) {
|
||||
const Region repaint((flags & DisplayHardware::UPDATE_ON_DEMAND) ?
|
||||
mDirtyRegion.bounds() : hw.bounds());
|
||||
composeSurfaces(repaint);
|
||||
}
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DITHER);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glColor4x(0x10000, 0, 0x10000, 0x10000);
|
||||
static int toggle = 0;
|
||||
toggle = 1 - toggle;
|
||||
if (toggle) {
|
||||
glColor4x(0x10000, 0, 0x10000, 0x10000);
|
||||
} else {
|
||||
glColor4x(0x10000, 0x10000, 0, 0x10000);
|
||||
}
|
||||
|
||||
Rect r;
|
||||
Region::iterator iterator(mDirtyRegion);
|
||||
@@ -919,8 +921,7 @@ void SurfaceFlinger::debugFlashRegions()
|
||||
glVertexPointer(2, GL_FLOAT, 0, vertices);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
|
||||
hw.flip(mDirtyRegion.merge(mInvalidRegion));
|
||||
mInvalidRegion.clear();
|
||||
|
||||
|
||||
@@ -55,8 +55,6 @@ class DisplayHardware;
|
||||
class FreezeLock;
|
||||
class Layer;
|
||||
class LayerBuffer;
|
||||
class LayerOrientationAnim;
|
||||
class OrientationAnimation;
|
||||
|
||||
typedef int32_t ClientID;
|
||||
|
||||
@@ -335,8 +333,6 @@ private:
|
||||
bool mFreezeDisplay;
|
||||
int32_t mFreezeCount;
|
||||
nsecs_t mFreezeDisplayTime;
|
||||
friend class OrientationAnimation;
|
||||
OrientationAnimation* mOrientationAnimation;
|
||||
|
||||
// don't use a lock for these, we don't care
|
||||
int mDebugRegion;
|
||||
|
||||
@@ -5,9 +5,9 @@ LOCAL_SRC_FILES:= \
|
||||
BufferMapper.cpp \
|
||||
Camera.cpp \
|
||||
CameraParameters.cpp \
|
||||
EGLNativeWindowSurface.cpp \
|
||||
EventHub.cpp \
|
||||
EventRecurrence.cpp \
|
||||
FramebufferNativeWindow.cpp \
|
||||
KeyLayoutMap.cpp \
|
||||
KeyCharacterMap.cpp \
|
||||
ICamera.cpp \
|
||||
|
||||
@@ -17,14 +17,9 @@
|
||||
#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>
|
||||
@@ -34,12 +29,6 @@
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// enable mapping debugging
|
||||
#define DEBUG_MAPPINGS 0
|
||||
// never remove mappings from the list
|
||||
#define DEBUG_MAPPINGS_KEEP_ALL 0
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -57,34 +46,27 @@ BufferMapper::BufferMapper()
|
||||
}
|
||||
}
|
||||
|
||||
status_t BufferMapper::map(buffer_handle_t handle, void** addr, const void* id)
|
||||
status_t BufferMapper::registerBuffer(buffer_handle_t handle)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
status_t err = mAllocMod->map(mAllocMod, handle, addr);
|
||||
LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
|
||||
#if DEBUG_MAPPINGS
|
||||
if (err == NO_ERROR)
|
||||
logMapLocked(handle, id);
|
||||
#endif
|
||||
status_t err = mAllocMod->registerBuffer(mAllocMod, handle);
|
||||
LOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
|
||||
handle, err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t BufferMapper::unmap(buffer_handle_t handle, const void* id)
|
||||
status_t BufferMapper::unregisterBuffer(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));
|
||||
#if DEBUG_MAPPINGS
|
||||
if (err == NO_ERROR)
|
||||
logUnmapLocked(handle, id);
|
||||
#endif
|
||||
status_t err = mAllocMod->unregisterBuffer(mAllocMod, handle);
|
||||
LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",
|
||||
handle, err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t BufferMapper::lock(buffer_handle_t handle, int usage, const Rect& bounds)
|
||||
status_t BufferMapper::lock(buffer_handle_t handle,
|
||||
int usage, const Rect& bounds, void** vaddr)
|
||||
{
|
||||
status_t err = mAllocMod->lock(mAllocMod, handle, usage,
|
||||
bounds.left, bounds.top, bounds.width(), bounds.height());
|
||||
bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr);
|
||||
LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
|
||||
return err;
|
||||
}
|
||||
@@ -96,65 +78,5 @@ status_t BufferMapper::unlock(buffer_handle_t handle)
|
||||
return err;
|
||||
}
|
||||
|
||||
void BufferMapper::logMapLocked(buffer_handle_t handle, const void* id)
|
||||
{
|
||||
CallStack stack;
|
||||
stack.update(2);
|
||||
|
||||
map_info_t info;
|
||||
info.id = id;
|
||||
info.stack = stack;
|
||||
|
||||
ssize_t index = mMapInfo.indexOfKey(handle);
|
||||
if (index >= 0) {
|
||||
Vector<map_info_t>& infos = mMapInfo.editValueAt(index);
|
||||
infos.add(info);
|
||||
} else {
|
||||
Vector<map_info_t> infos;
|
||||
infos.add(info);
|
||||
mMapInfo.add(handle, infos);
|
||||
}
|
||||
}
|
||||
|
||||
void BufferMapper::logUnmapLocked(buffer_handle_t handle, const void* id)
|
||||
{
|
||||
ssize_t index = mMapInfo.indexOfKey(handle);
|
||||
if (index < 0) {
|
||||
LOGE("unmapping %p which doesn't exist in our map!", handle);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<map_info_t>& infos = mMapInfo.editValueAt(index);
|
||||
ssize_t count = infos.size();
|
||||
for (int i=0 ; i<count ; ) {
|
||||
if (infos[i].id == id) {
|
||||
infos.removeAt(i);
|
||||
--count;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (count == 0) {
|
||||
mMapInfo.removeItemsAt(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void BufferMapper::dump(buffer_handle_t handle)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
ssize_t index = mMapInfo.indexOfKey(handle);
|
||||
if (index < 0) {
|
||||
LOGD("handle %p is not mapped through BufferMapper", handle);
|
||||
return;
|
||||
}
|
||||
|
||||
const Vector<map_info_t>& infos = mMapInfo.valueAt(index);
|
||||
ssize_t count = infos.size();
|
||||
for (int i=0 ; i<count ; i++) {
|
||||
LOGD("#%d", i);
|
||||
infos[i].stack.dump();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "EGLNativeWindowSurface"
|
||||
#define LOG_TAG "FramebufferNativeWindow"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include <ui/SurfaceComposerClient.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
#include <ui/FramebufferNativeWindow.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
@@ -87,13 +87,6 @@ FramebufferNativeWindow::FramebufferNativeWindow()
|
||||
|
||||
LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
|
||||
fbDev->width, fbDev->height, strerror(-err));
|
||||
|
||||
gralloc_module_t* m =
|
||||
reinterpret_cast<gralloc_module_t*>(grDev->common.module);
|
||||
|
||||
// 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;
|
||||
@@ -125,10 +118,7 @@ FramebufferNativeWindow::FramebufferNativeWindow()
|
||||
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;
|
||||
@@ -137,10 +127,6 @@ FramebufferNativeWindow::FramebufferNativeWindow()
|
||||
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);
|
||||
}
|
||||
@@ -160,13 +146,10 @@ int FramebufferNativeWindow::setSwapInterval(
|
||||
return fb->setSwapInterval(fb, interval);
|
||||
}
|
||||
|
||||
int FramebufferNativeWindow::setSwapRectangle(android_native_window_t* window,
|
||||
int l, int t, int w, int h)
|
||||
void FramebufferNativeWindow::setSwapRectangle(const Rect& dirty)
|
||||
{
|
||||
FramebufferNativeWindow* self = getSelf(window);
|
||||
Mutex::Autolock _l(self->mutex);
|
||||
self->mDirty = Rect(l, t, l+w, t+h);
|
||||
return 0;
|
||||
Mutex::Autolock _l(mutex);
|
||||
mDirty = dirty;
|
||||
}
|
||||
|
||||
int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window,
|
||||
@@ -201,16 +184,8 @@ int FramebufferNativeWindow::lockBuffer(android_native_window_t* window,
|
||||
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;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int FramebufferNativeWindow::queueBuffer(android_native_window_t* window,
|
||||
@@ -219,13 +194,8 @@ int FramebufferNativeWindow::queueBuffer(android_native_window_t* window,
|
||||
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();
|
||||
@@ -88,6 +88,13 @@ void Region::set(const Rect& r)
|
||||
mRegion.setRect(ir);
|
||||
}
|
||||
|
||||
void Region::set(uint32_t w, uint32_t h)
|
||||
{
|
||||
SkIRect ir;
|
||||
ir.set(0, 0, w, h);
|
||||
mRegion.setRect(ir);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Region& Region::orSelf(const Rect& r)
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/BufferMapper.h>
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
#include <ui/ISurface.h>
|
||||
#include <ui/Surface.h>
|
||||
#include <ui/SurfaceComposerClient.h>
|
||||
@@ -53,7 +52,7 @@ namespace android {
|
||||
ANDROID_SINGLETON_STATIC_INSTANCE( SurfaceBuffer )
|
||||
|
||||
SurfaceBuffer::SurfaceBuffer()
|
||||
: BASE(), handle(0), mOwner(false)
|
||||
: BASE(), handle(0), mOwner(false), mBufferMapper(BufferMapper::get())
|
||||
{
|
||||
width =
|
||||
height =
|
||||
@@ -64,7 +63,7 @@ SurfaceBuffer::SurfaceBuffer()
|
||||
}
|
||||
|
||||
SurfaceBuffer::SurfaceBuffer(const Parcel& data)
|
||||
: BASE(), handle(0), mOwner(true)
|
||||
: BASE(), handle(0), mOwner(true), mBufferMapper(BufferMapper::get())
|
||||
{
|
||||
// we own the handle in this case
|
||||
width = data.readInt32();
|
||||
@@ -91,6 +90,26 @@ int SurfaceBuffer::getHandle(android_native_buffer_t const * base,
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t SurfaceBuffer::lock(uint32_t usage)
|
||||
{
|
||||
const Rect lockBounds(width, height);
|
||||
status_t res = lock(usage, lockBounds);
|
||||
return res;
|
||||
}
|
||||
|
||||
status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect)
|
||||
{
|
||||
status_t res = getBufferMapper().lock(handle, usage, rect, &bits);
|
||||
return res;
|
||||
}
|
||||
|
||||
status_t SurfaceBuffer::unlock()
|
||||
{
|
||||
status_t res = getBufferMapper().unlock(handle);
|
||||
bits = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
status_t SurfaceBuffer::writeToParcel(Parcel* reply,
|
||||
android_native_buffer_t const* buffer)
|
||||
{
|
||||
@@ -110,9 +129,17 @@ status_t SurfaceBuffer::writeToParcel(Parcel* reply,
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
static void copyBlt(const android_native_buffer_t* dst,
|
||||
const android_native_buffer_t* src, const Region& reg)
|
||||
static void copyBlt(
|
||||
const sp<SurfaceBuffer>& dst,
|
||||
const sp<SurfaceBuffer>& src,
|
||||
const Region& reg)
|
||||
{
|
||||
src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds());
|
||||
uint8_t const * const src_bits = (uint8_t const *)src->bits;
|
||||
|
||||
dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds());
|
||||
uint8_t* const dst_bits = (uint8_t*)dst->bits;
|
||||
|
||||
Region::iterator iterator(reg);
|
||||
if (iterator) {
|
||||
// NOTE: dst and src must be the same format
|
||||
@@ -120,29 +147,29 @@ static void copyBlt(const android_native_buffer_t* dst,
|
||||
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);
|
||||
ssize_t h = r.height();
|
||||
if (h <= 0) continue;
|
||||
size_t size = r.width() * bpp;
|
||||
uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
|
||||
uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
|
||||
if (dbpr==sbpr && size==sbpr) {
|
||||
size *= h;
|
||||
h = 1;
|
||||
}
|
||||
do {
|
||||
memcpy(d, s, size);
|
||||
d += dbpr;
|
||||
s += sbpr;
|
||||
} while (--h > 0);
|
||||
}
|
||||
}
|
||||
|
||||
src->unlock();
|
||||
dst->unlock();
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// SurfaceControl
|
||||
// ============================================================================
|
||||
@@ -347,12 +374,14 @@ sp<Surface> SurfaceControl::getSurface() const
|
||||
Surface::Surface(const sp<SurfaceControl>& surface)
|
||||
: mClient(surface->mClient), mSurface(surface->mSurface),
|
||||
mToken(surface->mToken), mIdentity(surface->mIdentity),
|
||||
mFormat(surface->mFormat), mFlags(surface->mFlags)
|
||||
mFormat(surface->mFormat), mFlags(surface->mFlags),
|
||||
mBufferMapper(BufferMapper::get())
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
Surface::Surface(const Parcel& parcel)
|
||||
: mBufferMapper(BufferMapper::get())
|
||||
{
|
||||
sp<IBinder> clientBinder = parcel.readStrongBinder();
|
||||
mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
|
||||
@@ -369,16 +398,11 @@ Surface::Surface(const Parcel& parcel)
|
||||
|
||||
void Surface::init()
|
||||
{
|
||||
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();
|
||||
|
||||
DisplayInfo dinfo;
|
||||
SurfaceComposerClient::getDisplayInfo(0, &dinfo);
|
||||
const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
|
||||
@@ -396,7 +420,7 @@ Surface::~Surface()
|
||||
// its buffers in this process.
|
||||
for (int i=0 ; i<2 ; i++) {
|
||||
if (mBuffers[i] != 0) {
|
||||
BufferMapper::get().unmap(mBuffers[i]->getHandle(), this);
|
||||
getBufferMapper().unregisterBuffer(mBuffers[i]->getHandle());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,22 +467,6 @@ bool Surface::isSameSurface(
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
@@ -487,6 +495,26 @@ int Surface::queueBuffer(android_native_window_t* window,
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
|
||||
{
|
||||
android_native_buffer_t* out;
|
||||
status_t err = dequeueBuffer(&out);
|
||||
*buffer = SurfaceBuffer::getSelf(out);
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t Surface::lockBuffer(const sp<SurfaceBuffer>& buffer)
|
||||
{
|
||||
return lockBuffer(buffer.get());
|
||||
}
|
||||
|
||||
status_t Surface::queueBuffer(const sp<SurfaceBuffer>& buffer)
|
||||
{
|
||||
return queueBuffer(buffer.get());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int Surface::dequeueBuffer(android_native_buffer_t** buffer)
|
||||
{
|
||||
// FIXME: dequeueBuffer() needs proper implementation
|
||||
@@ -515,8 +543,9 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
|
||||
}
|
||||
|
||||
const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
|
||||
mDirtyRegion.set(backBuffer->width, backBuffer->height);
|
||||
*buffer = backBuffer.get();
|
||||
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -542,11 +571,14 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
|
||||
if (err != NO_ERROR)
|
||||
return err;
|
||||
|
||||
if (mSwapRectangle.isValid()) {
|
||||
mDirtyRegion.set(mSwapRectangle);
|
||||
}
|
||||
|
||||
// transmit the dirty region
|
||||
const Region dirty(swapRectangle());
|
||||
SurfaceID index(mToken);
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[index]);
|
||||
_send_dirty_region(lcblk, dirty);
|
||||
_send_dirty_region(lcblk, mDirtyRegion);
|
||||
|
||||
uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
|
||||
if (!(newstate & eNextFlipPending))
|
||||
@@ -561,27 +593,20 @@ status_t Surface::lock(SurfaceInfo* info, bool blocking) {
|
||||
return Surface::lock(info, NULL, blocking);
|
||||
}
|
||||
|
||||
status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
|
||||
status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
|
||||
{
|
||||
// FIXME: needs some locking here
|
||||
android_native_buffer_t* backBuffer;
|
||||
|
||||
sp<SurfaceBuffer> 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;
|
||||
Region scratch(bounds);
|
||||
Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
|
||||
|
||||
per_client_cblk_t* const cblk = mClient->mControl;
|
||||
layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
|
||||
@@ -590,43 +615,34 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
|
||||
// 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;
|
||||
} else {
|
||||
newDirtyRegion.andSelf(bounds);
|
||||
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);
|
||||
const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
|
||||
const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
|
||||
if (!copyback.isEmpty() && frontBuffer!=0) {
|
||||
// copy front to back
|
||||
copyBlt(backBuffer, frontBuffer, copyback);
|
||||
}
|
||||
}
|
||||
}
|
||||
setDirtyRegion(newDirtyRegion);
|
||||
mDirtyRegion = newDirtyRegion;
|
||||
mOldDirtyRegion = 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);
|
||||
status_t res = backBuffer->lock(
|
||||
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
|
||||
newDirtyRegion.bounds());
|
||||
|
||||
LOGW_IF(res, "failed locking buffer %d (%p)",
|
||||
mBackbufferIndex, handle);
|
||||
setSwapRectangle(lockBounds);
|
||||
mBackbufferIndex, backBuffer->handle);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
@@ -639,16 +655,12 @@ status_t Surface::unlockAndPost()
|
||||
if (mLockedBuffer == 0)
|
||||
return BAD_VALUE;
|
||||
|
||||
buffer_handle_t handle;
|
||||
mLockedBuffer->getHandle(mLockedBuffer, &handle);
|
||||
status_t res = BufferMapper::get().unlock(handle);
|
||||
status_t res = mLockedBuffer->unlock();
|
||||
LOGW_IF(res, "failed unlocking buffer %d (%p)",
|
||||
mBackbufferIndex, handle);
|
||||
|
||||
const Rect dirty(dirtyRegion().bounds());
|
||||
setSwapRectangle(dirty);
|
||||
mBackbufferIndex, mLockedBuffer->handle);
|
||||
|
||||
status_t err = queueBuffer(mLockedBuffer);
|
||||
mLockedBuffer->common.decRef(&mLockedBuffer->common);
|
||||
mLockedBuffer->bits = NULL;
|
||||
mLockedBuffer = 0;
|
||||
return err;
|
||||
}
|
||||
@@ -666,15 +678,6 @@ void Surface::_send_dirty_region(
|
||||
}
|
||||
}
|
||||
|
||||
Region Surface::dirtyRegion() const {
|
||||
return mDirtyRegion;
|
||||
}
|
||||
void Surface::setDirtyRegion(const Region& region) const {
|
||||
mDirtyRegion = region;
|
||||
}
|
||||
const Rect& Surface::swapRectangle() const {
|
||||
return mSwapRectangle;
|
||||
}
|
||||
void Surface::setSwapRectangle(const Rect& r) {
|
||||
mSwapRectangle = r;
|
||||
}
|
||||
@@ -687,10 +690,10 @@ status_t Surface::getBufferLocked(int index)
|
||||
if (buffer != 0) {
|
||||
sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
|
||||
if (currentBuffer != 0) {
|
||||
BufferMapper::get().unmap(currentBuffer->getHandle(), this);
|
||||
getBufferMapper().unregisterBuffer(currentBuffer->getHandle());
|
||||
currentBuffer.clear();
|
||||
}
|
||||
err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits, this);
|
||||
err = getBufferMapper().registerBuffer(buffer->getHandle());
|
||||
LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
|
||||
if (err == NO_ERROR) {
|
||||
currentBuffer = buffer;
|
||||
|
||||
@@ -96,18 +96,6 @@ struct android_native_window_t
|
||||
/* 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.
|
||||
@@ -117,20 +105,10 @@ struct android_native_window_t
|
||||
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.
|
||||
* this call may block if no buffers are available.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
@@ -179,7 +157,7 @@ struct android_native_buffer_t
|
||||
int stride;
|
||||
int format;
|
||||
int usage;
|
||||
void* bits; // non-zero if buffer is mmaped
|
||||
void* bits; // non-zero if buffer is locked for sw usage
|
||||
|
||||
void* reserved[2];
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
EGLTextureObject::EGLTextureObject()
|
||||
: mCount(0), mSize(0)
|
||||
: mSize(0)
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -56,6 +56,7 @@ void EGLTextureObject::init()
|
||||
#ifdef LIBAGL_USE_GRALLOC_COPYBITS
|
||||
copybits_fd = -1;
|
||||
#endif // LIBAGL_USE_GRALLOC_COPYBITS
|
||||
buffer = 0;
|
||||
}
|
||||
|
||||
void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old)
|
||||
@@ -126,6 +127,7 @@ status_t EGLTextureObject::setSurface(GGLSurface const* s)
|
||||
}
|
||||
surface = *s;
|
||||
internalformat = 0;
|
||||
buffer = 0;
|
||||
|
||||
// we should keep the crop_rect, but it's delicate because
|
||||
// the new size of the surface could make it invalid.
|
||||
@@ -144,6 +146,20 @@ status_t EGLTextureObject::setSurface(GGLSurface const* s)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t EGLTextureObject::setImage(android_native_buffer_t* native_buffer)
|
||||
{
|
||||
GGLSurface sur;
|
||||
sur.version = sizeof(GGLSurface);
|
||||
sur.width = native_buffer->width;
|
||||
sur.height= native_buffer->height;
|
||||
sur.stride= native_buffer->stride;
|
||||
sur.format= native_buffer->format;
|
||||
sur.data = 0;
|
||||
setSurface(&sur);
|
||||
buffer = native_buffer;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t EGLTextureObject::reallocate(
|
||||
GLint level, int w, int h, int s,
|
||||
int format, int compressedFormat, int bpr)
|
||||
@@ -227,7 +243,7 @@ status_t EGLTextureObject::reallocate(
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
EGLSurfaceManager::EGLSurfaceManager()
|
||||
: TokenManager(), mCount(0)
|
||||
: TokenManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <private/pixelflinger/ggl_context.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <EGL/android_natives.h>
|
||||
|
||||
#include "Tokenizer.h"
|
||||
#include "TokenManager.h"
|
||||
@@ -39,22 +40,20 @@ namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class EGLTextureObject
|
||||
class EGLTextureObject : public LightRefBase<EGLTextureObject>
|
||||
{
|
||||
public:
|
||||
EGLTextureObject();
|
||||
~EGLTextureObject();
|
||||
|
||||
// protocol for sp<>
|
||||
inline void incStrong(const void* id) const;
|
||||
inline void decStrong(const void* id) const;
|
||||
inline uint32_t getStrongCount() const;
|
||||
status_t setSurface(GGLSurface const* s);
|
||||
status_t setImage(android_native_buffer_t* buffer);
|
||||
void setImageBits(void* vaddr) { surface.data = (GGLubyte*)vaddr; }
|
||||
|
||||
status_t setSurface(GGLSurface const* s);
|
||||
status_t reallocate(GLint level,
|
||||
int w, int h, int s,
|
||||
int format, int compressedFormat, int bpr);
|
||||
inline size_t size() const;
|
||||
inline size_t size() const { return mSize; }
|
||||
const GGLSurface& mip(int lod) const;
|
||||
GGLSurface& editMip(int lod);
|
||||
bool hasMipmaps() const { return mMipmaps!=0; }
|
||||
@@ -65,7 +64,6 @@ private:
|
||||
status_t allocateMipmaps();
|
||||
void freeMipmaps();
|
||||
void init();
|
||||
mutable int32_t mCount;
|
||||
size_t mSize;
|
||||
GGLSurface *mMipmaps;
|
||||
int mNumExtraLod;
|
||||
@@ -84,36 +82,19 @@ public:
|
||||
#ifdef LIBAGL_USE_GRALLOC_COPYBITS
|
||||
int copybits_fd;
|
||||
#endif // LIBAGL_USE_GRALLOC_COPYBITS
|
||||
android_native_buffer_t* buffer;
|
||||
};
|
||||
|
||||
void EGLTextureObject::incStrong(const void* id) const {
|
||||
android_atomic_inc(&mCount);
|
||||
}
|
||||
void EGLTextureObject::decStrong(const void* id) const {
|
||||
if (android_atomic_dec(&mCount) == 1) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
uint32_t EGLTextureObject::getStrongCount() const {
|
||||
return mCount;
|
||||
}
|
||||
size_t EGLTextureObject::size() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class EGLSurfaceManager : public TokenManager
|
||||
class EGLSurfaceManager :
|
||||
public LightRefBase<EGLSurfaceManager>,
|
||||
public TokenManager
|
||||
{
|
||||
public:
|
||||
EGLSurfaceManager();
|
||||
~EGLSurfaceManager();
|
||||
|
||||
// protocol for sp<>
|
||||
inline void incStrong(const void* id) const;
|
||||
inline void decStrong(const void* id) const;
|
||||
typedef void weakref_type;
|
||||
|
||||
sp<EGLTextureObject> createTexture(GLuint name);
|
||||
sp<EGLTextureObject> removeTexture(GLuint name);
|
||||
sp<EGLTextureObject> replaceTexture(GLuint name);
|
||||
@@ -121,21 +102,10 @@ public:
|
||||
sp<EGLTextureObject> texture(GLuint name);
|
||||
|
||||
private:
|
||||
mutable int32_t mCount;
|
||||
mutable Mutex mLock;
|
||||
KeyedVector< GLuint, sp<EGLTextureObject> > mTextures;
|
||||
};
|
||||
|
||||
void EGLSurfaceManager::incStrong(const void* id) const {
|
||||
android_atomic_inc(&mCount);
|
||||
}
|
||||
void EGLSurfaceManager::decStrong(const void* id) const {
|
||||
if (android_atomic_dec(&mCount) == 1) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
|
||||
@@ -1371,9 +1371,18 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count)
|
||||
if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK))
|
||||
return; // all triangles are culled
|
||||
|
||||
|
||||
validate_arrays(c, mode);
|
||||
|
||||
const uint32_t enables = c->rasterizer.state.enables;
|
||||
if (enables & GGL_ENABLE_TMUS)
|
||||
ogles_lock_textures(c);
|
||||
|
||||
drawArraysPrims[mode](c, first, count);
|
||||
|
||||
if (enables & GGL_ENABLE_TMUS)
|
||||
ogles_unlock_textures(c);
|
||||
|
||||
#if VC_CACHE_STATISTICS
|
||||
c->vc.total = count;
|
||||
c->vc.dump_stats(mode);
|
||||
@@ -1425,8 +1434,16 @@ void glDrawElements(
|
||||
indices = c->arrays.element_array_buffer->data + uintptr_t(indices);
|
||||
}
|
||||
|
||||
drawElementsPrims[mode](c, count, indices);
|
||||
const uint32_t enables = c->rasterizer.state.enables;
|
||||
if (enables & GGL_ENABLE_TMUS)
|
||||
ogles_lock_textures(c);
|
||||
|
||||
drawElementsPrims[mode](c, count, indices);
|
||||
|
||||
if (enables & GGL_ENABLE_TMUS)
|
||||
ogles_unlock_textures(c);
|
||||
|
||||
|
||||
#if VC_CACHE_STATISTICS
|
||||
c->vc.total = count;
|
||||
c->vc.dump_stats(mode);
|
||||
|
||||
@@ -212,8 +212,11 @@ struct egl_window_surface_v2_t : public egl_surface_t
|
||||
virtual EGLint getRefreshRate() const;
|
||||
virtual EGLint getSwapBehavior() const;
|
||||
private:
|
||||
status_t lock(android_native_buffer_t* buf, int usage);
|
||||
status_t unlock(android_native_buffer_t* buf);
|
||||
android_native_window_t* nativeWindow;
|
||||
android_native_buffer_t* buffer;
|
||||
gralloc_module_t const* module;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
@@ -222,8 +225,13 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
|
||||
EGLConfig config,
|
||||
int32_t depthFormat,
|
||||
android_native_window_t* window)
|
||||
: egl_surface_t(dpy, config, depthFormat), nativeWindow(window), buffer(0)
|
||||
: egl_surface_t(dpy, config, depthFormat),
|
||||
nativeWindow(window), buffer(0), module(0)
|
||||
{
|
||||
hw_module_t const* pModule;
|
||||
hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
|
||||
module = reinterpret_cast<gralloc_module_t const*>(pModule);
|
||||
|
||||
nativeWindow->common.incRef(&nativeWindow->common);
|
||||
|
||||
nativeWindow->dequeueBuffer(nativeWindow, &buffer);
|
||||
@@ -246,13 +254,44 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
|
||||
buffer->common.incRef(&buffer->common);
|
||||
nativeWindow->lockBuffer(nativeWindow, buffer);
|
||||
|
||||
// FIXME: we need to gralloc lock the buffer
|
||||
// Lock the buffer
|
||||
lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
|
||||
|
||||
// FIXME: we need to handle the copy-back if needed, but
|
||||
// for now we're a "non preserving" implementation.
|
||||
}
|
||||
|
||||
status_t egl_window_surface_v2_t::lock(
|
||||
android_native_buffer_t* buf, int usage)
|
||||
{
|
||||
int err;
|
||||
buffer_handle_t bufferHandle;
|
||||
err = buf->getHandle(buf, &bufferHandle);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = module->lock(module, bufferHandle,
|
||||
usage, 0, 0, buf->width, buf->height, &buf->bits);
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
|
||||
{
|
||||
int err;
|
||||
buffer_handle_t bufferHandle;
|
||||
err = buf->getHandle(buf, &bufferHandle);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = module->unlock(module, bufferHandle);
|
||||
buf->bits = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
egl_window_surface_v2_t::~egl_window_surface_v2_t() {
|
||||
if (buffer) {
|
||||
unlock(buffer);
|
||||
buffer->common.decRef(&buffer->common);
|
||||
}
|
||||
nativeWindow->common.decRef(&nativeWindow->common);
|
||||
@@ -269,6 +308,7 @@ EGLBoolean egl_window_surface_v2_t::swapBuffers()
|
||||
//mDisplaySurface->copyFrontToBack(copyback);
|
||||
|
||||
|
||||
unlock(buffer);
|
||||
nativeWindow->queueBuffer(nativeWindow, buffer);
|
||||
buffer->common.decRef(&buffer->common); buffer = 0;
|
||||
|
||||
@@ -278,6 +318,7 @@ EGLBoolean egl_window_surface_v2_t::swapBuffers()
|
||||
// TODO: lockBuffer should rather be executed when the very first
|
||||
// direct rendering occurs.
|
||||
nativeWindow->lockBuffer(nativeWindow, buffer);
|
||||
lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
|
||||
|
||||
|
||||
if ((width != buffer->width) || (height != buffer->height)) {
|
||||
@@ -1690,20 +1731,6 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
|
||||
|
||||
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);
|
||||
int err = module->map(module, bufferHandle, &native_buffer->bits);
|
||||
if (err < 0) {
|
||||
LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
|
||||
return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
|
||||
}
|
||||
|
||||
native_buffer->common.incRef(&native_buffer->common);
|
||||
return (EGLImageKHR)native_buffer;
|
||||
@@ -1723,18 +1750,6 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
|
||||
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);
|
||||
int err = native_buffer->getHandle(native_buffer, &bufferHandle);
|
||||
if (err == 0) {
|
||||
int err = module->unmap(module, bufferHandle);
|
||||
LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err));
|
||||
}
|
||||
}
|
||||
|
||||
native_buffer->common.decRef(&native_buffer->common);
|
||||
|
||||
return EGL_TRUE;
|
||||
|
||||
@@ -103,7 +103,7 @@ void validate_tmu(ogles_context_t* c, int i)
|
||||
}
|
||||
}
|
||||
|
||||
void ogles_validate_texture_impl(ogles_context_t* c)
|
||||
void ogles_validate_texture(ogles_context_t* c)
|
||||
{
|
||||
for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
|
||||
if (c->rasterizer.state.texture[i].enable)
|
||||
@@ -117,6 +117,67 @@ void invalidate_texture(ogles_context_t* c, int tmu, uint8_t flags = 0xFF) {
|
||||
c->textures.tmu[tmu].dirty = flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the active textures are EGLImage, they need to be locked before
|
||||
* they can be used.
|
||||
*
|
||||
* FIXME: code below is far from being optimal
|
||||
*
|
||||
*/
|
||||
|
||||
void ogles_lock_textures(ogles_context_t* c)
|
||||
{
|
||||
for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
|
||||
if (c->rasterizer.state.texture[i].enable) {
|
||||
texture_unit_t& u(c->textures.tmu[i]);
|
||||
android_native_buffer_t* native_buffer = u.texture->buffer;
|
||||
if (native_buffer) {
|
||||
c->rasterizer.procs.activeTexture(c, i);
|
||||
hw_module_t const* pModule;
|
||||
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
|
||||
continue;
|
||||
|
||||
gralloc_module_t const* module =
|
||||
reinterpret_cast<gralloc_module_t const*>(pModule);
|
||||
buffer_handle_t bufferHandle;
|
||||
native_buffer->getHandle(native_buffer, &bufferHandle);
|
||||
int err = module->lock(module, bufferHandle,
|
||||
GRALLOC_USAGE_SW_READ_OFTEN,
|
||||
0, 0, native_buffer->width, native_buffer->height,
|
||||
&native_buffer->bits);
|
||||
|
||||
u.texture->setImageBits(native_buffer->bits);
|
||||
c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ogles_unlock_textures(ogles_context_t* c)
|
||||
{
|
||||
for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
|
||||
if (c->rasterizer.state.texture[i].enable) {
|
||||
texture_unit_t& u(c->textures.tmu[i]);
|
||||
android_native_buffer_t* native_buffer = u.texture->buffer;
|
||||
if (native_buffer) {
|
||||
c->rasterizer.procs.activeTexture(c, i);
|
||||
hw_module_t const* pModule;
|
||||
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
|
||||
continue;
|
||||
|
||||
gralloc_module_t const* module =
|
||||
reinterpret_cast<gralloc_module_t const*>(pModule);
|
||||
buffer_handle_t bufferHandle;
|
||||
native_buffer->getHandle(native_buffer, &bufferHandle);
|
||||
module->unlock(module, bufferHandle);
|
||||
u.texture->setImageBits(NULL);
|
||||
c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
|
||||
}
|
||||
}
|
||||
}
|
||||
c->rasterizer.procs.activeTexture(c, c->textures.active);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#if 0
|
||||
#pragma mark -
|
||||
@@ -592,6 +653,8 @@ invalid_enum:
|
||||
static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
|
||||
ogles_context_t* c)
|
||||
{
|
||||
ogles_lock_textures(c);
|
||||
|
||||
const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
|
||||
y = gglIntToFixed(cbSurface.height) - (y + h);
|
||||
w >>= FIXED_BITS;
|
||||
@@ -650,6 +713,8 @@ static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h
|
||||
gglFixedToIntRound(y),
|
||||
gglFixedToIntRound(x)+w,
|
||||
gglFixedToIntRound(y)+h);
|
||||
|
||||
ogles_unlock_textures(c);
|
||||
}
|
||||
|
||||
static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
|
||||
@@ -724,6 +789,8 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte
|
||||
goto slow_case;
|
||||
}
|
||||
|
||||
ogles_lock_textures(c);
|
||||
|
||||
c->rasterizer.procs.texCoord2i(c, s0, t0);
|
||||
const uint32_t enables = c->rasterizer.state.enables;
|
||||
if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)))
|
||||
@@ -734,6 +801,9 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte
|
||||
c->rasterizer.procs.disable(c, GGL_AA);
|
||||
c->rasterizer.procs.shadeModel(c, GL_FLAT);
|
||||
c->rasterizer.procs.recti(c, x, y, x+w, y+h);
|
||||
|
||||
ogles_unlock_textures(c);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1460,23 +1530,9 @@ void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
|
||||
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);
|
||||
tex->setImage(native_buffer);
|
||||
|
||||
/*
|
||||
* Here an implementation can retrieve the buffer_handle_t of this buffer
|
||||
|
||||
@@ -32,13 +32,9 @@ namespace android {
|
||||
|
||||
void ogles_init_texture(ogles_context_t* c);
|
||||
void ogles_uninit_texture(ogles_context_t* c);
|
||||
void ogles_validate_texture_impl(ogles_context_t* c);
|
||||
|
||||
inline void ogles_validate_texture(ogles_context_t* c) {
|
||||
if (c->rasterizer.state.enables & GGL_ENABLE_TMUS)
|
||||
ogles_validate_texture_impl(c);
|
||||
}
|
||||
|
||||
void ogles_validate_texture(ogles_context_t* c);
|
||||
void ogles_lock_textures(ogles_context_t* c);
|
||||
void ogles_unlock_textures(ogles_context_t* c);
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
||||
@@ -14,5 +14,5 @@ LOCAL_MODULE:= test-opengl-copybits
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
##include $(BUILD_EXECUTABLE)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user