diff --git a/tools/emulator/opengl/system/OpenglSystemCommon/gralloc_cb.h b/tools/emulator/opengl/system/OpenglSystemCommon/gralloc_cb.h new file mode 100644 index 000000000..3bfabc831 --- /dev/null +++ b/tools/emulator/opengl/system/OpenglSystemCommon/gralloc_cb.h @@ -0,0 +1,76 @@ +#ifndef __GRALLOC_CB_H__ +#define __GRALLOC_CB_H__ + +#include +#include +#include + +#define BUFFER_HANDLE_MAGIC ((int)0xabfabfab) +#define CB_HANDLE_NUM_INTS(nfds) ((sizeof(cb_handle_t) - (nfds)*sizeof(int)) / sizeof(int)) + +// +// Our buffer handle structure +// +struct cb_handle_t : public native_handle { + + cb_handle_t(int p_fd, int p_ashmemSize, int p_usage, + int p_width, int p_height, int p_glFormat) : + fd(p_fd), + magic(BUFFER_HANDLE_MAGIC), + usage(p_usage), + width(p_width), + height(p_height), + glFormat(p_glFormat), + ashmemSize(p_ashmemSize), + ashmemBase(NULL), + ashmemBasePid(0), + mappedPid(0), + lockedLeft(0), + lockedTop(0), + lockedWidth(0), + lockedHeight(0), + hostHandle(0) + { + version = sizeof(native_handle); + numFds = 1; + numInts = CB_HANDLE_NUM_INTS(numFds); + } + + ~cb_handle_t() { + magic = 0; + } + + bool validate() const { + return (version == sizeof(native_handle) && + magic == BUFFER_HANDLE_MAGIC && + numInts == CB_HANDLE_NUM_INTS(1) && + numFds == 1); + } + + bool canBePosted() { + return (0 != (usage & GRALLOC_USAGE_HW_FB)); + } + + // file-descriptors + int fd; // ashmem fd (-1 of ashmem region did not allocated, i.e. no SW access needed) + + // ints + int magic; // magic number in order to validate a pointer to be a cb_handle_t + int usage; // usage bits the buffer was created with + int width; // buffer width + int height; // buffer height + int glFormat; // OpenGL format enum used for host h/w color buffer + int ashmemSize; // ashmem region size for the buffer (0 unless is HW_FB buffer or + // s/w access is needed) + int ashmemBase; // CPU address of the mapped ashmem region + int ashmemBasePid; // process id which mapped the ashmem region + int mappedPid; // process id which succeeded gralloc_register call + int lockedLeft; // region of buffer locked for s/w write + int lockedTop; + int lockedWidth; + int lockedHeight; + uint32_t hostHandle; +}; + + +#endif //__GRALLOC_CB_H__ diff --git a/tools/emulator/opengl/system/egl/egl.cpp b/tools/emulator/opengl/system/egl/egl.cpp index d186f2e9a..ed8329586 100644 --- a/tools/emulator/opengl/system/egl/egl.cpp +++ b/tools/emulator/opengl/system/egl/egl.cpp @@ -18,6 +18,7 @@ #include "eglDisplay.h" #include "egl_ftable.h" #include +#include "gralloc_cb.h" #include @@ -91,7 +92,7 @@ struct EGLContext_t { NEVER_CURRENT = 0x00020000 }; - EGLContext_t(EGLDisplay dpy, EGLConfig config) : dpy(dpy), config(config), read(EGL_NO_SURFACE), draw(EGL_NO_SURFACE), rcContext(0) {}; + EGLContext_t(EGLDisplay dpy, EGLConfig config) : dpy(dpy), config(config), read(EGL_NO_SURFACE), draw(EGL_NO_SURFACE), rcContext(0) { version = 1; }; ~EGLContext_t(){}; // EGLBoolean rcCreate(); // EGLBoolean rcDestroy(); @@ -100,6 +101,7 @@ struct EGLContext_t { EGLConfig config; EGLSurface read; EGLSurface draw; + EGLint version; uint32_t rcContext; }; @@ -115,18 +117,24 @@ struct egl_surface_t { egl_surface_t(EGLDisplay dpy, EGLConfig config); virtual ~egl_surface_t(); - virtual EGLBoolean rcCreate() = 0; - virtual EGLBoolean rcDestroy() = 0; - void setRcSurface(uint32_t handle){ rcSurface = handle; } - uint32_t getRcSurface(){ return rcSurface; } + + virtual EGLBoolean rcCreate() = 0; + virtual EGLBoolean rcDestroy() = 0; + + virtual EGLBoolean connect() { return EGL_TRUE; } + virtual void disconnect() {} + virtual EGLBoolean swapBuffers() { return EGL_TRUE; } + + 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 + EGLBoolean valid; + uint32_t rcSurface; //handle to surface created via remote control }; egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config) @@ -143,21 +151,29 @@ egl_surface_t::~egl_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 rcCreate(); virtual EGLBoolean rcDestroy(); + virtual EGLBoolean connect(); + virtual void disconnect(); + virtual EGLBoolean swapBuffers(); + + virtual EGLint getWidth() const { return width; } + virtual EGLint getHeight() const { return height; } + + +private: + ANativeWindow* nativeWindow; + int width; + int height; + android_native_buffer_t* buffer; + }; @@ -171,7 +187,6 @@ egl_window_surface_t::egl_window_surface_t ( 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() { @@ -204,6 +219,44 @@ EGLBoolean egl_window_surface_t::rcDestroy() return EGL_TRUE; } +EGLBoolean egl_window_surface_t::connect() +{ + // dequeue a buffer + if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) { + return setError(EGL_BAD_ALLOC, EGL_FALSE); + } + + DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); + rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, ((cb_handle_t *)(buffer->handle))->hostHandle); + + return EGL_TRUE; +} + +void egl_window_surface_t::disconnect() +{ + //TODO: do we need this? +} + +EGLBoolean egl_window_surface_t::swapBuffers() +{ + if (!buffer) { + return setError(EGL_BAD_ACCESS, EGL_FALSE); + } + + //post the back buffer + nativeWindow->queueBuffer(nativeWindow, buffer); + + // dequeue a new buffer + if (nativeWindow->dequeueBuffer(nativeWindow, &buffer)) { + return setError(EGL_BAD_ALLOC, EGL_FALSE); + } + + DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); + rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, ((cb_handle_t *)(buffer->handle))->hostHandle); + + return EGL_TRUE; +} + // ---------------------------------------------------------------------------- //egl_pbuffer_surface_t @@ -390,10 +443,44 @@ EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) { +#if 0 VALIDATE_DISPLAY_INIT(dpy, NULL); - //TODO - return 0; + //First construct a vector of all configs + Vector possibleConfigs; + for (int i=0; i(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } @@ -491,7 +577,7 @@ EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePix EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) { - VALIDATE_DISPLAY_INIT(dpy, NULL); + VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE); egl_surface_t* surface( static_cast(eglSurface) ); @@ -502,10 +588,30 @@ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) return EGL_TRUE; } -EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value) { - //TODO - return 0; + VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); + VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE); + + egl_surface_t* surface( static_cast(eglSurface) ); + EGLBoolean ret = EGL_TRUE; + switch (attribute) { + case EGL_CONFIG_ID: + ret = s_display.getConfigAttrib(surface->config, EGL_CONFIG_ID, value); + break; + case EGL_WIDTH: + *value = surface->getWidth(); + break; + case EGL_HEIGHT: + *value = surface->getHeight(); + break; + //TODO: complete other attributes + default: + ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + break; + } + + return ret; } EGLBoolean eglBindAPI(EGLenum api) @@ -567,7 +673,6 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_c VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT); VALIDATE_CONFIG(config, EGL_NO_CONTEXT); - EGLint version = 1; //default while (attrib_list[0]) { if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1]; @@ -593,6 +698,7 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_c if (!context) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + context->version = 1; context->rcContext = rcContext; @@ -650,6 +756,10 @@ EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLC //Now make current getEGLThreadInfo()->currentContext = context; + //connect the color buffer + if (drawSurf) + drawSurf->connect(); + return EGL_TRUE; } @@ -685,8 +795,33 @@ EGLDisplay eglGetCurrentDisplay() EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) { - //TODO - return 0; + VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); + VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE); + + EGLContext_t * context = static_cast(ctx); + + EGLBoolean ret = EGL_TRUE; + switch (attribute) { + case EGL_CONFIG_ID: + ret = s_display.getConfigAttrib(context->config, EGL_CONFIG_ID, value); + break; + case EGL_CONTEXT_CLIENT_TYPE: + *value = EGL_OPENGL_ES_API; + break; + case EGL_CONTEXT_CLIENT_VERSION: + *value = context->version; + break; + case EGL_RENDER_BUFFER: + if (!context->draw) + *value = EGL_NONE; + else + *value = EGL_BACK_BUFFER; //single buffer not supported + break; + default: + return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + + return ret; } EGLBoolean eglWaitGL() @@ -701,10 +836,22 @@ EGLBoolean eglWaitNative(EGLint engine) return 0; } -EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) +EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface) { - //TODO - return 0; + VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); + if (eglSurface == EGL_NO_SURFACE) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + + egl_surface_t* d = static_cast(eglSurface); + if (!d->isValid()) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (d->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + // post the surface + d->swapBuffers(); + + return EGL_TRUE; } EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) diff --git a/tools/emulator/opengl/system/egl/eglDisplay.cpp b/tools/emulator/opengl/system/egl/eglDisplay.cpp index 086ed9b8c..54eb55e96 100644 --- a/tools/emulator/opengl/system/egl/eglDisplay.cpp +++ b/tools/emulator/opengl/system/egl/eglDisplay.cpp @@ -168,7 +168,7 @@ bool eglDisplay::initialize(EGLClient_eglInterface *eglIface) } //Copy the actual configs data to m_configs - memcpy(m_configs, tmp_buf + m_numConfigAttribs*sizeof(EGLint), m_numConfigs*sizeof(EGLint)); + memcpy(m_configs, tmp_buf + m_numConfigAttribs, m_numConfigs*sizeof(EGLint)); m_initialized = true; } @@ -367,6 +367,9 @@ const char *eglDisplay::queryString(EGLint name) } } +/* To get the value of attribute of config use the following formula: + * value = *(m_configs + (int)c*m_numConfigAttribs + a); + */ EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint * value) { if (attribIdx == ATTRIBUTE_NONE) diff --git a/tools/emulator/opengl/system/egl/eglDisplay.h b/tools/emulator/opengl/system/egl/eglDisplay.h index 4ab420b00..6f3685485 100644 --- a/tools/emulator/opengl/system/egl/eglDisplay.h +++ b/tools/emulator/opengl/system/egl/eglDisplay.h @@ -62,7 +62,14 @@ private: int m_hostRendererVersion; int m_numConfigs; int m_numConfigAttribs; - DefaultKeyedVector m_attribs; + + /* This is the mapping between an attribute name to it's index in any given config */ + DefaultKeyedVector m_attribs; + /* This is an array of all config's attributes values stored in the following sequencial fasion (read: v[c,a] = the value of attribute of config ) + * v[0,0],..,v[0,m_numConfigAttribs-1], + *... + * v[m_numConfigs-1,0],..,v[m_numConfigs-1,m_numConfigAttribs-1] + */ EGLint *m_configs; EGLClient_glesInterface *m_gles_iface; EGLClient_glesInterface *m_gles2_iface; diff --git a/tools/emulator/opengl/system/gralloc/gralloc.cpp b/tools/emulator/opengl/system/gralloc/gralloc.cpp index 8aafd468e..abc01a0e9 100644 --- a/tools/emulator/opengl/system/gralloc/gralloc.cpp +++ b/tools/emulator/opengl/system/gralloc/gralloc.cpp @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include -#include -#include +#include "gralloc_cb.h" #include #ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define # include @@ -30,7 +28,6 @@ #include "glUtils.h" #include -#define BUFFER_HANDLE_MAGIC ((int)0xabfabfab) // // our private gralloc module structure @@ -62,72 +59,6 @@ struct fb_device_t { framebuffer_device_t device; }; -#define CB_HANDLE_NUM_INTS(nfds) ((sizeof(cb_handle_t) - (nfds)*sizeof(int)) / sizeof(int)) - -// -// Our buffer handle structure -// -struct cb_handle_t : public native_handle { - - cb_handle_t(int p_fd, int p_ashmemSize, int p_usage, - int p_width, int p_height, int p_glFormat) : - fd(p_fd), - magic(BUFFER_HANDLE_MAGIC), - usage(p_usage), - width(p_width), - height(p_height), - glFormat(p_glFormat), - ashmemSize(p_ashmemSize), - ashmemBase(NULL), - ashmemBasePid(0), - mappedPid(0), - lockedLeft(0), - lockedTop(0), - lockedWidth(0), - lockedHeight(0), - hostHandle(0) - { - version = sizeof(native_handle); - numFds = 1; - numInts = CB_HANDLE_NUM_INTS(numFds); - } - - ~cb_handle_t() { - magic = 0; - } - - bool validate() const { - return (version == sizeof(native_handle) && - magic == BUFFER_HANDLE_MAGIC && - numInts == CB_HANDLE_NUM_INTS(1) && - numFds == 1); - } - - bool canBePosted() { - return (0 != (usage & GRALLOC_USAGE_HW_FB)); - } - - // file-descriptors - int fd; // ashmem fd (-1 of ashmem region did not allocated, i.e. no SW access needed) - - // ints - int magic; // magic number in order to validate a pointer to be a cb_handle_t - int usage; // usage bits the buffer was created with - int width; // buffer width - int height; // buffer height - int glFormat; // OpenGL format enum used for host h/w color buffer - int ashmemSize; // ashmem region size for the buffer (0 unless is HW_FB buffer or - // s/w access is needed) - int ashmemBase; // CPU address of the mapped ashmem region - int ashmemBasePid; // process id which mapped the ashmem region - int mappedPid; // process id which succeeded gralloc_register call - int lockedLeft; // region of buffer locked for s/w write - int lockedTop; - int lockedWidth; - int lockedHeight; - uint32_t hostHandle; -}; - static int map_buffer(cb_handle_t *cb, void **vaddr) { if (cb->fd < 0 || cb->ashmemSize <= 0) {