am 3389c10a: am 96deb3b2: Merge "emulator opengl: Create and destroy Surfaces"

* commit '3389c10a1057038b213c85d5180f8199f956c0b8':
  emulator opengl: Create and destroy Surfaces
This commit is contained in:
David Turner
2011-06-14 12:59:31 -07:00
committed by Android Git Automerger
4 changed files with 328 additions and 29 deletions

View File

@@ -35,7 +35,8 @@ LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_STATIC_LIBRARIES := \
libOpenglSystemCommon \
libOpenglCodecCommon
libOpenglCodecCommon \
libqemu
LOCAL_SHARED_LIBRARIES := \
libcutils \

View File

@@ -19,12 +19,13 @@
#include "egl_ftable.h"
#include <cutils/log.h>
// The one and only supported display object.
static eglDisplay s_display;
#include <private/ui/android_natives_priv.h>
static EGLClient_eglInterface s_eglIface = {
getThreadInfo: getEGLThreadInfo
};
template<typename T>
static T setError(GLint error, T returnValue) {
getEGLThreadInfo()->eglError = error;
return returnValue;
}
#define RETURN_ERROR(ret,err) \
getEGLThreadInfo()->eglError = err; \
@@ -48,6 +49,206 @@ static EGLClient_eglInterface s_eglIface = {
return ret; \
}
#define DEFINE_HOST_CONNECTION \
HostConnection *hostCon = HostConnection::get(); \
renderControl_encoder_context_t *rcEnc = (hostCon ? hostCon->rcEncoder() : NULL)
#define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
HostConnection *hostCon = HostConnection::get(); \
if (!hostCon) { \
LOGE("egl: Failed to get host connection\n"); \
return ret; \
} \
renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
if (!rcEnc) { \
LOGE("egl: Failed to get renderControl encoder context\n"); \
return ret; \
}
// ----------------------------------------------------------------------------
//egl_surface_t
//we don't need to handle depth since it's handled when window created on the host
struct egl_surface_t {
EGLDisplay dpy;
EGLConfig config;
EGLContext ctx;
egl_surface_t(EGLDisplay dpy, EGLConfig config);
virtual ~egl_surface_t();
virtual EGLBoolean createRc() = 0;
virtual EGLBoolean destroyRc() = 0;
void setRcSurface(uint32_t handle){ rcSurface = handle; }
uint32_t getRcSurface(){ return rcSurface; }
virtual EGLBoolean isValid(){ return valid; }
virtual EGLint getWidth() const = 0;
virtual EGLint getHeight() const = 0;
protected:
EGLBoolean valid;
uint32_t rcSurface; //handle to surface created via remote control
};
egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config)
: dpy(dpy), config(config), ctx(0), valid(EGL_FALSE), rcSurface(0)
{
}
egl_surface_t::~egl_surface_t()
{
}
// ----------------------------------------------------------------------------
// egl_window_surface_t
struct egl_window_surface_t : public egl_surface_t {
ANativeWindow* nativeWindow;
int width;
int height;
virtual EGLint getWidth() const { return width; }
virtual EGLint getHeight() const { return height; }
egl_window_surface_t(
EGLDisplay dpy, EGLConfig config,
ANativeWindow* window);
~egl_window_surface_t();
virtual EGLBoolean createRc();
virtual EGLBoolean destroyRc();
};
egl_window_surface_t::egl_window_surface_t (
EGLDisplay dpy, EGLConfig config,
ANativeWindow* window)
: egl_surface_t(dpy, config),
nativeWindow(window)
{
// keep a reference on the window
nativeWindow->common.incRef(&nativeWindow->common);
nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
}
egl_window_surface_t::~egl_window_surface_t() {
nativeWindow->common.decRef(&nativeWindow->common);
}
EGLBoolean egl_window_surface_t::createRc()
{
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
uint32_t rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config, getWidth(), getHeight());
if (!rcSurface) {
LOGE("rcCreateWindowSurface returned 0");
return EGL_FALSE;
}
valid = EGL_TRUE;
return EGL_TRUE;
}
EGLBoolean egl_window_surface_t::destroyRc()
{
if (!rcSurface) {
LOGE("destroyRc called on invalid rcSurface");
return EGL_FALSE;
}
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
rcSurface = 0;
return EGL_TRUE;
}
// ----------------------------------------------------------------------------
//egl_pbuffer_surface_t
struct egl_pbuffer_surface_t : public egl_surface_t {
int width;
int height;
GLenum format;
virtual EGLint getWidth() const { return width; }
virtual EGLint getHeight() const { return height; }
egl_pbuffer_surface_t(
EGLDisplay dpy, EGLConfig config,
int32_t w, int32_t h, GLenum format);
virtual ~egl_pbuffer_surface_t();
virtual EGLBoolean createRc();
virtual EGLBoolean destroyRc();
uint32_t getRcColorBuffer(){ return rcColorBuffer; }
void setRcColorBuffer(uint32_t colorBuffer){ rcColorBuffer = colorBuffer; }
private:
uint32_t rcColorBuffer;
};
egl_pbuffer_surface_t::egl_pbuffer_surface_t(
EGLDisplay dpy, EGLConfig config,
int32_t w, int32_t h, GLenum pixelFormat)
: egl_surface_t(dpy, config),
width(w), height(h), format(pixelFormat)
{
}
egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
{
rcColorBuffer = 0;
}
EGLBoolean egl_pbuffer_surface_t::createRc()
{
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uint32_t)config, getWidth(), getHeight());
if (!rcSurface) {
LOGE("rcCreateWindowSurface returned 0");
return EGL_FALSE;
}
rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), format);
if (!rcColorBuffer) {
LOGE("rcCreateColorBuffer returned 0");
return EGL_FALSE;
}
valid = EGL_TRUE;
return EGL_TRUE;
}
EGLBoolean egl_pbuffer_surface_t::destroyRc()
{
if ((!rcSurface)||(!rcColorBuffer)) {
LOGE("destroyRc called on invalid rcSurface");
return EGL_FALSE;
}
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
rcEnc->rcDestroyColorBuffer(rcEnc, rcColorBuffer);
rcSurface = 0;
return EGL_TRUE;
}
// ----------------------------------------------------------------------------
// The one and only supported display object.
static eglDisplay s_display;
static EGLClient_eglInterface s_eglIface = {
getThreadInfo: getEGLThreadInfo
};
EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
{
//
@@ -164,40 +365,102 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute
VALIDATE_DISPLAY_INIT(dpy, NULL);
VALIDATE_CONFIG(config, EGL_FALSE);
EGLint attribVal = s_display.getConfigAttrib(config, attribute);
if (attribVal == ATTRIBUTE_NONE) {
if (s_display.getConfigAttrib(config, attribute, value))
{
return EGL_TRUE;
}
else
{
RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
}
*value = attribVal;
return EGL_TRUE;
}
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
{
//TODO
return 0;
VALIDATE_DISPLAY_INIT(dpy, NULL);
VALIDATE_CONFIG(config, EGL_FALSE);
if (win == 0)
{
return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
EGLint surfaceType;
if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
if (!(surfaceType & EGL_WINDOW_BIT)) {
return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
egl_surface_t* surface;
surface = new egl_window_surface_t(&s_display, config, static_cast<ANativeWindow*>(win));
if (!surface) setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
if (!surface->createRc()) setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
return surface;
}
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
{
//TODO
return 0;
VALIDATE_DISPLAY_INIT(dpy, NULL);
VALIDATE_CONFIG(config, EGL_FALSE);
EGLint surfaceType;
if (s_display.getConfigAttrib(config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE;
if (!(surfaceType & EGL_PBUFFER_BIT)) {
return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
int32_t w = 0;
int32_t h = 0;
while (attrib_list[0]) {
if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1];
if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
attrib_list+=2;
}
GLenum pixelFormat;
if (s_display.getConfigPixelFormat(config, &pixelFormat) == EGL_FALSE)
return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
egl_surface_t* surface = new egl_pbuffer_surface_t(dpy, config, w, h, pixelFormat);
if (!surface) setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
if (!surface->createRc()) setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
return surface;
}
EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
{
//TODO
return 0;
//XXX: Pixmap not supported. The host cannot render to a pixmap resource
// located on host. In order to support Pixmaps we should either punt
// to s/w rendering -or- let the host render to a buffer that will be
// copied back to guest at some sync point. None of those methods not
// implemented and pixmaps are not used with OpenGL anyway ...
return EGL_NO_SURFACE;
}
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
{
//TODO
return 0;
VALIDATE_DISPLAY_INIT(dpy, NULL);
if (eglSurface != EGL_NO_SURFACE)
{
egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
if (!surface->isValid())
return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (surface->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
surface->destroyRc();
delete surface;
}
return EGL_TRUE;
}
EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)

View File

@@ -367,10 +367,42 @@ const char *eglDisplay::queryString(EGLint name)
}
}
EGLint eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib)
EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint * value)
{
EGLint attrIdx = m_attribs.valueFor(attrib);
if (attrIdx == ATTRIBUTE_NONE) return ATTRIBUTE_NONE;
else return *(m_configs + (int)config*m_numConfigAttribs + attrIdx);
if (attribIdx == ATTRIBUTE_NONE)
{
LOGE("[%s] Bad attribute idx\n", __FUNCTION__);
return EGL_FALSE;
}
*value = *(m_configs + (int)config*m_numConfigAttribs + attribIdx);
return EGL_TRUE;
}
EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value)
{
return getAttribValue(config, m_attribs.valueFor(attrib), value);
}
EGLBoolean eglDisplay::getConfigPixelFormat(EGLConfig config, GLenum * format)
{
EGLint redSize, blueSize, greenSize, alphaSize;
if ( !(getAttribValue(config, m_attribs.valueFor(EGL_RED_SIZE), &redSize) &&
getAttribValue(config, m_attribs.valueFor(EGL_BLUE_SIZE), &blueSize) &&
getAttribValue(config, m_attribs.valueFor(EGL_GREEN_SIZE), &greenSize) &&
getAttribValue(config, m_attribs.valueFor(EGL_ALPHA_SIZE), &alphaSize)) )
{
LOGE("Couldn't find value for one of the pixel format attributes");
return EGL_FALSE;
}
//calculate the GL internal format
if ((redSize==8)&&(blueSize==8)&&(greenSize==8)&&(alphaSize==8)) *format = GL_RGBA;
else if ((redSize==8)&&(blueSize==8)&&(greenSize==8)&&(alphaSize==0)) *format = GL_RGB;
else if ((redSize==5)&&(blueSize==6)&&(greenSize==5)&&(alphaSize==0)) *format = GL_RGB565_OES;
else if ((redSize==5)&&(blueSize==5)&&(greenSize==5)&&(alphaSize==1)) *format = GL_RGB5_A1_OES;
else if ((redSize==4)&&(blueSize==4)&&(greenSize==4)&&(alphaSize==4)) *format = GL_RGBA4_OES;
else return EGL_FALSE;
return EGL_TRUE;
}

View File

@@ -17,6 +17,7 @@
#define _SYSTEM_EGL_DISPLAY_H
#include <pthread.h>
#include "glUtils.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "EGLClientIface.h"
@@ -44,12 +45,14 @@ public:
const EGLClient_glesInterface *gles2_iface() const { return m_gles2_iface; }
int getNumConfigs(){ return m_numConfigs; }
EGLint getConfigAttrib(EGLConfig config, EGLint attrib);
EGLBoolean getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value);
EGLBoolean getConfigPixelFormat(EGLConfig config, GLenum * format);
private:
EGLClient_glesInterface *loadGLESClientAPI(const char *libName,
EGLClient_eglInterface *eglIface,
void **libHandle);
EGLBoolean getAttribValue(EGLConfig config, EGLint attribIdxi, EGLint * value);
private:
pthread_mutex_t m_lock;