Files
android_development/tools/emulator/opengl/system/egl/egl.cpp
bohu f8ac5e3178 back port gles fix to api 17
Following CLs are ported:

        717e625415c4398431b84851ba1b76d8c59ae9cf Add shader version to glGetString
        32c30975ea654b9654ad9dade0d25b9856e63f1b Add parameters validation to glShaderSource() API
        b0c7cce25bf9323a359800a86c0c7609db2acea4 Fix eglDestroyContext and glTexImage2D
        2fc65202c214640c55b52c29bbc9213170d0b533 handles glGetBooleanv when value is nonboolean
        beda8027439b9c20475b8a3d379823d09fca3abb Properly initialize GLClientState's m_states
        84684ec571a1db94e32a67cb7d154ab562dd0d7f Unbind buffer when buffer is deleted
        89b7aac84f8babab93ff5326ad492164d971c421 Handle empty data parameter in glTexSubImage2D_enc
        adb0f74f792ba7bca20257b9c0ea41ebda9bb229 Allow glGetProgramInfoLog_enc to have empty length
        b31166704ddb7751619cf0bbc4f2f4575c0ad3c4 Guard against negative buffer size
        641f35af08a0a4c46586a592ff4e703e866d581a Guard against negative width and height
        9d18698dd8da15937f80e5476d73400a011934be Handle empty buffer in QemuPipeStream::writeFully
        40a674e0d0acac87aa25eb9de720dc2fb07d9e4f Fix emulator crashes on glDrawElements command
        7fa2b92de2058a3556e5f38a135de415bb3d5e45 Merge "Use more appropriate type in cb_handle_t::validate."
        fe2c5beb964d2e2aecedb02b9cca592e0811d90b Use more appropriate type in cb_handle_t::validate.
        376688e76694bf5b8672379c540b1bda059da682 Merge "ranchu: Fix goldfish_pipe definitions."
        e3e686593cc8bdaf3ca4f6fa0b33b62a6951d1d6 ranchu: Fix goldfish_pipe definitions.
        7d3d0c99d2c82319e001289d1b9e091e5ff8f7aa Merge "ranchu: Add ARM64-specific root/ramdisk config files."
        d0fead3c53d6e450deb69aad72651e132b6cc072 ranchu: Add ARM64-specific root/ramdisk config files.
        638ee524f83053613c47ddea22c4bf98a0175c2f Merge "Remove display initialization from eglGetProcAddress API"
        7a2929cd6548693b581c17ba69308a49e03c56be Remove display initialization from eglGetProcAddress API
        9b1e6c5a3ccd943b7158dce83387fbfcc1162d69 Merge "Make the size of "cb_handle_t" same for 32/64-bit"
        7ea757df0311bfb7310a7a765dcec1b79f39f25d Merge "goldfish: camera: fix 64-bit warnings"
        3725c7c982eac52ec64a625e82f306822452941c goldfish: camera: fix 64-bit warnings
        eed789f036cbcedf2fa96ae3e273c2234102d340 Merge "goldfish: Fix /cache partition type."
        f55ac4fc027ae3d97f4faaa6ccd65480f493dea7 goldfish: Fix /cache partition type.
        690792a66c7fca6bf0aa17c2d5043ab86d145965 Merge "Revert "Revert "goldfish: cache image is not ext4. yet."""
        8853df9503e0edec6cac0e1e0840fa111d57a79a Revert "Revert "goldfish: cache image is not ext4. yet.""
        d8a6e67044ddcac7c53adbe6b871c33447110905 Merge "Revert "goldfish: cache image is not ext4. yet.""
        5e2caf7883279113d6f5f4777122dc88262c34c6 Revert "goldfish: cache image is not ext4. yet."
        3f62b50d45441ae077c958423e9e301acd5dcc11 Make the size of "cb_handle_t" same for 32/64-bit
        aec15d91ee48797f2b3c3fe61cca977900ebcd47 am 646f0b25: Merge "opengl: rcOpenColorBuffer must be synchronous"
        646f0b25e63164950d1d99b9b8021be74c2321c6 Merge "opengl: rcOpenColorBuffer must be synchronous"
        c542f3d8fc89678574b2fa650395f3dfac991a20 opengl: rcOpenColorBuffer must be synchronous
        6ccaeebd78dcb5e20e2c0e81cdc571fb74f9cfb7 am 2c6c08a2: Merge "Move goldfish from fdprintf to POSIX dprintf."
        2c6c08a23d2f5f760753745be5b67fe5759dcc91 Merge "Move goldfish from fdprintf to POSIX dprintf."
        0228f8a1cdf5b2391201333de73fabab6d2ca72f Move goldfish from fdprintf to POSIX dprintf.
        dbda557d4dcf022850ea4ab4f89e1c154e2aea04 am 5cb5779a: Merge "gralloc: don\'t initialize reserved_proc"
        5cb5779ad0ad75a59bfb8ce42317a4ee18300281 Merge "gralloc: don't initialize reserved_proc"
        e46eea0b5bdef28f5c42e4d7764b030679479354 gralloc: don't initialize reserved_proc
        67334d0b9d0da7595daf07a3e9bea6a55436e296 Merge commit 'd9dc763708823aa865983bb8dc37b5ecc5669620' into HEAD
        7076e4647af737393baf020c13e81a090f4a9f26 Merge "Add 64-bit software GLES/EGL support in gralloc.goldfish module"
        3f92be74c1e9b2314d4c0f8feaacf7bafce7dedc Add 64-bit software GLES/EGL support in gralloc.goldfish module
        61a8f0bbc146a4050a885e1e7c314dfc4ab72779 Merge "Fix the Chrome app crash in emulator issue"
        bd93fee73b02d0b223b441c34a4f8e04eb57291d Merge "Support GLES acceleration in 64bit emulator on device side"
        a1de8e2f5e4c29341be01bae364a54d92d14c742 Fix the Chrome app crash in emulator issue
        4f94a5f8b13a5fdd80988e77dd5d468b958b0117 Merge "Remove the useless folder and files in emulator GLES/EGL drivers"
        31aad5c0a0de056114b6bb843a5c37d8de6e46e4 Remove the useless folder and files in emulator GLES/EGL drivers
        aedc716648071a1403f4ac92a380d1d4a5377052 Support GLES acceleration in 64bit emulator on device side
        d9dc763708823aa865983bb8dc37b5ecc5669620 am aedf829a: Merge "goldfish: cache image is not ext4. yet."
        aedf829a920c3100de5caa49b0dec02d66eed96b Merge "goldfish: cache image is not ext4. yet."
        a2543be45f35ab7ace3ecd92c99a3c72150622ec goldfish: cache image is not ext4. yet.
        9dba558f4621d3d70a05c0a3d8e2c34b3883f866 am 48a76778: Merge "Remove #include <asm/page.h>."
        644f53c8705586705c27b799e5b5f303118e8b3c am 155ca91c: Merge topic \'emu64\'
        48a76778937abadf5cbd260696a29d737134d0d9 Merge "Remove #include <asm/page.h>."
        1daf365476f888a5d9534607c8299a3b5160b4a7 Remove #include <asm/page.h>.
        155ca91c1253bcb85a0eeec93ded6da07122d4ff Merge topic 'emu64'
        324a0c43835b935721c938a2684874e0b5bf8311 Disable echo on all tty lines
        8bb5f92dcd48dbbaa69ab15f97aca13d49b08599 ueventd.goldfish.rc: set system permissions for /dev/goldfish_pipe
        5b31b113176dec8d7fcfb5650f3dd7b01baf605c am 48107fa1: Merge "device/generic/goldfish: convert LOCAL_MODULE_PATH to LOCAL_MODULE_RELATIVE_PATH"
        48107fa1dd354f8667b74f335c3f82f472b7d112 Merge "device/generic/goldfish: convert LOCAL_MODULE_PATH to LOCAL_MODULE_RELATIVE_PATH"
        5212e4a903d2654572b8bdde0bda3bdd6ecbee6e device/generic/goldfish: convert LOCAL_MODULE_PATH to LOCAL_MODULE_RELATIVE_PATH
        2061519f3e55ba1dac643cac34a4aa6f0f0dfeee am 44c72ca0: Merge "Vibra: Add the vibrator module for goldfish"
        44c72ca0b92c75ffef5e691a24d5d06d6a3e7baa Merge "Vibra: Add the vibrator module for goldfish"
        0f41b57f2aa2ffa8fd90ebd50c13c2dd0249ee0f Vibra: Add the vibrator module for goldfish
        ac534df6c39944a91f157819628db3d6f63b75f1 am 59922432: Merge commit \'f09bc5256e48a44eec9ca47ba838c12d0e89a198\' into HEAD
        59922432be859a46eeb76650b24308505625da36 Merge commit 'f09bc5256e48a44eec9ca47ba838c12d0e89a198' into HEAD
        144d2d5d683928f393a9567c443c8f5af13dfdd0 am b9a62053: Merge commit \'828bd482a1aeacf96d5f3a3e0701029d9f890c5f\' into HEAD
        b9a62053cf74025a43c8baa118d52729e38cc176 Merge commit '828bd482a1aeacf96d5f3a3e0701029d9f890c5f' into HEAD
        a648b35cca58d3d1608e1beb21028f91bd0b9df7 am 2befc3ed: Merge "Modify the build targets for goldfish from to include aosp*."
        2befc3edc583afb43a4f6740f0af0534eac8e9d5 Merge "Modify the build targets for goldfish from to include aosp*."
        bc233492e3ce3af8cc23496ee58cd3dc1b74d0f0 Modify the build targets for goldfish from to include aosp*.
        f09bc5256e48a44eec9ca47ba838c12d0e89a198 am b9a7de1a: Merge "Delete buffer data when removing it from the SharedGroup namespace"
        b9a7de1a690bc638496e0550e6a9ebe859fc0315 Merge "Delete buffer data when removing it from the SharedGroup namespace"
        8562d1b6e089254837da3ab2d272c65c3bb5d8c7 Delete buffer data when removing it from the SharedGroup namespace
        f8b99f123467cd6164d071237f5dbe703f9ea2d7 am 6b151ca8: Merge "Catch divide by zero case in drawCheckerBoard() function."
        6b151ca8833aa7271e311436dad97588b71b7a38 Merge "Catch divide by zero case in drawCheckerBoard() function."
        d7cc5da79d828ec6cb21926be13265fc52715e2f am 84309165: Merge "Drop setting of in_qemu boolean and restorecon /sys/qemu_trace."
        84309165ca52b7446e388c13127fd6e305833f24 Merge "Drop setting of in_qemu boolean and restorecon /sys/qemu_trace."
        46bcb5f7a64ccd440d5a292c7afd2e2b5c2bee4f Drop setting of in_qemu boolean and restorecon /sys/qemu_trace.
        b0b6afb44269263afa080ecc643f2c4866adfb38 Catch divide by zero case in drawCheckerBoard() function.
        828bd482a1aeacf96d5f3a3e0701029d9f890c5f am 2524d396: Update emulator to FUSE-wrap its SD card.
        2524d39681566f4eca7afb7950e05ab642978263 Update emulator to FUSE-wrap its SD card.
        e8122dff1ef2de4d41835265a59d8960e7800fae camera3: Fix stream id types
        3ad13188d4e7e873947040ec22a35d73efb76812 Camera2/3: Implement full-color NV21 output.
        a4c19be9274d8bb993f88a6a1cbd2ad92f4a48fa Merge "Added net.dns1 prop for emulator, as Android emulator ignores it by default."
        ccb835ba267e927f7df759290bd46ac78712a3b2 Merge "Camera2/3: Update static metadata"
        0049ee8925212a3a5ff095a8a66cab184adf8f1b Camera2/3: Update static metadata
        8ff1e5f1e3e24baf311e6263b48f389c206f14ac am 8f9288ea: goldfish: use fstab.goldfish
        8f9288eaf10b50d19038f5c7024616e147c64735 goldfish: use fstab.goldfish
        e96a7c7da79939c509a7517f2b2de37e840a6390 Added net.dns1 prop for emulator, as Android emulator ignores it by default.
        ff3a362fb9aca15285a95cad6baa08e961330e8e am bf34d172: (-s ours) Reconcile with jb-mr2-zeroday-release - do not merge
        bf34d1722ea1ebdf779837611220b5269bd35968 Reconcile with jb-mr2-zeroday-release - do not merge
        d9fcbd08b0413fedc8219237534ce31d6b7fd2f5 merge in jb-mr2-zeroday-release history after reset to jb-mr2-dev
        ad9dd4bfdfa9ab6ccfc4be14305b6ed8b9a0ab5a am 2c84e47e: am 07a4c8b4: Camera3: Fix default AE mode
        2c84e47e3d0085b1222de94013c75c0328b02492 am 07a4c8b4: Camera3: Fix default AE mode

Change-Id: I3902e73cf96f9d64d56d939dce2673ad5710f6cb
2015-02-03 17:42:11 -08:00

1273 lines
37 KiB
C++

/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "HostConnection.h"
#include "ThreadInfo.h"
#include "eglDisplay.h"
#include "egl_ftable.h"
#include <cutils/log.h>
#include "gralloc_cb.h"
#include "GLClientState.h"
#include "GLSharedGroup.h"
#include "eglContext.h"
#include "ClientAPIExts.h"
#include "GLEncoder.h"
#ifdef WITH_GLES2
#include "GL2Encoder.h"
#endif
#include <system/window.h>
template<typename T>
static T setErrorFunc(GLint error, T returnValue) {
getEGLThreadInfo()->eglError = error;
return returnValue;
}
const char * eglStrError(EGLint err)
{
switch (err){
case EGL_SUCCESS: return "EGL_SUCCESS";
case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
default: return "UNKNOWN";
}
}
#define LOG_EGL_ERRORS 1
#ifdef LOG_EGL_ERRORS
#define setErrorReturn(error, retVal) \
{ \
ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, error, eglStrError(error)); \
return setErrorFunc(error, retVal); \
}
#define RETURN_ERROR(ret,err) \
ALOGE("tid %d: %s(%d): error 0x%x (%s)", gettid(), __FUNCTION__, __LINE__, err, eglStrError(err)); \
getEGLThreadInfo()->eglError = err; \
return ret;
#else //!LOG_EGL_ERRORS
#define setErrorReturn(error, retVal) return setErrorFunc(error, retVal);
#define RETURN_ERROR(ret,err) \
getEGLThreadInfo()->eglError = err; \
return ret;
#endif //LOG_EGL_ERRORS
#define VALIDATE_CONFIG(cfg,ret) \
if(((intptr_t)cfg<0)||((intptr_t)cfg>s_display.getNumConfigs())) { \
RETURN_ERROR(ret,EGL_BAD_CONFIG); \
}
#define VALIDATE_DISPLAY(dpy,ret) \
if ((dpy) != (EGLDisplay)&s_display) { \
RETURN_ERROR(ret, EGL_BAD_DISPLAY); \
}
#define VALIDATE_DISPLAY_INIT(dpy,ret) \
VALIDATE_DISPLAY(dpy, ret) \
if (!s_display.initialized()) { \
RETURN_ERROR(ret, EGL_NOT_INITIALIZED); \
}
#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) { \
ALOGE("egl: Failed to get host connection\n"); \
return ret; \
} \
renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
if (!rcEnc) { \
ALOGE("egl: Failed to get renderControl encoder context\n"); \
return ret; \
}
#define VALIDATE_CONTEXT_RETURN(context,ret) \
if (!context) { \
RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
}
#define VALIDATE_SURFACE_RETURN(surface, ret) \
if (surface != EGL_NO_SURFACE) { \
egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
if (s->dpy != (EGLDisplay)&s_display) \
setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
}
EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
dpy(dpy),
config(config),
read(EGL_NO_SURFACE),
draw(EGL_NO_SURFACE),
shareCtx(shareCtx),
rcContext(0),
versionString(NULL),
vendorString(NULL),
rendererString(NULL),
shaderVersionString(NULL),
extensionString(NULL),
deletePending(0)
{
flags = 0;
version = 1;
clientState = new GLClientState();
if (shareCtx)
sharedGroup = shareCtx->getSharedGroup();
else
sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
};
EGLContext_t::~EGLContext_t()
{
delete clientState;
delete [] versionString;
delete [] vendorString;
delete [] rendererString;
delete [] shaderVersionString;
delete [] extensionString;
}
// ----------------------------------------------------------------------------
//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;
egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
virtual ~egl_surface_t();
virtual void setSwapInterval(int interval) = 0;
virtual EGLBoolean swapBuffers() = 0;
EGLint getSwapBehavior() const;
uint32_t getRcSurface() { return rcSurface; }
EGLint getSurfaceType() { return surfaceType; }
EGLint getWidth(){ return width; }
EGLint getHeight(){ return height; }
void setTextureFormat(EGLint _texFormat) { texFormat = _texFormat; }
EGLint getTextureFormat() { return texFormat; }
void setTextureTarget(EGLint _texTarget) { texTarget = _texTarget; }
EGLint getTextureTarget() { return texTarget; }
private:
//
//Surface attributes
//
EGLint width;
EGLint height;
EGLint texFormat;
EGLint texTarget;
protected:
void setWidth(EGLint w) { width = w; }
void setHeight(EGLint h) { height = h; }
EGLint surfaceType;
uint32_t rcSurface; //handle to surface created via remote control
};
egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
: dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
{
width = 0;
height = 0;
texFormat = EGL_NO_TEXTURE;
texTarget = EGL_NO_TEXTURE;
}
EGLint egl_surface_t::getSwapBehavior() const {
return EGL_BUFFER_PRESERVED;
}
egl_surface_t::~egl_surface_t()
{
}
// ----------------------------------------------------------------------------
// egl_window_surface_t
struct egl_window_surface_t : public egl_surface_t {
static egl_window_surface_t* create(
EGLDisplay dpy, EGLConfig config, EGLint surfType,
ANativeWindow* window);
virtual ~egl_window_surface_t();
virtual void setSwapInterval(int interval);
virtual EGLBoolean swapBuffers();
private:
egl_window_surface_t(
EGLDisplay dpy, EGLConfig config, EGLint surfType,
ANativeWindow* window);
EGLBoolean init();
ANativeWindow* nativeWindow;
android_native_buffer_t* buffer;
};
egl_window_surface_t::egl_window_surface_t (
EGLDisplay dpy, EGLConfig config, EGLint surfType,
ANativeWindow* window)
: egl_surface_t(dpy, config, surfType),
nativeWindow(window),
buffer(NULL)
{
// keep a reference on the window
nativeWindow->common.incRef(&nativeWindow->common);
EGLint w,h;
nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &w);
setWidth(w);
nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &h);
setHeight(h);
}
EGLBoolean egl_window_surface_t::init()
{
if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer) != NO_ERROR) {
setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
}
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
getWidth(), getHeight());
if (!rcSurface) {
ALOGE("rcCreateWindowSurface returned 0");
return EGL_FALSE;
}
rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
((cb_handle_t*)(buffer->handle))->hostHandle);
return EGL_TRUE;
}
egl_window_surface_t* egl_window_surface_t::create(
EGLDisplay dpy, EGLConfig config, EGLint surfType,
ANativeWindow* window)
{
egl_window_surface_t* wnd = new egl_window_surface_t(
dpy, config, surfType, window);
if (wnd && !wnd->init()) {
delete wnd;
wnd = NULL;
}
return wnd;
}
egl_window_surface_t::~egl_window_surface_t() {
DEFINE_HOST_CONNECTION;
if (rcSurface && rcEnc) {
rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
}
if (buffer) {
nativeWindow->cancelBuffer_DEPRECATED(nativeWindow, buffer);
}
nativeWindow->common.decRef(&nativeWindow->common);
}
void egl_window_surface_t::setSwapInterval(int interval)
{
nativeWindow->setSwapInterval(nativeWindow, interval);
}
EGLBoolean egl_window_surface_t::swapBuffers()
{
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buffer);
if (nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buffer)) {
buffer = NULL;
setErrorReturn(EGL_BAD_ALLOC, EGL_FALSE);
}
rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface,
((cb_handle_t *)(buffer->handle))->hostHandle);
return EGL_TRUE;
}
// ----------------------------------------------------------------------------
//egl_pbuffer_surface_t
struct egl_pbuffer_surface_t : public egl_surface_t {
static egl_pbuffer_surface_t* create(EGLDisplay dpy, EGLConfig config,
EGLint surfType, int32_t w, int32_t h, GLenum pixelFormat);
virtual ~egl_pbuffer_surface_t();
virtual void setSwapInterval(int interval) {}
virtual EGLBoolean swapBuffers() { return EGL_TRUE; }
uint32_t getRcColorBuffer() { return rcColorBuffer; }
private:
egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfType,
int32_t w, int32_t h);
EGLBoolean init(GLenum format);
uint32_t rcColorBuffer;
};
egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, EGLConfig config,
EGLint surfType, int32_t w, int32_t h)
: egl_surface_t(dpy, config, surfType),
rcColorBuffer(0)
{
setWidth(w);
setHeight(h);
}
egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
{
DEFINE_HOST_CONNECTION;
if (rcEnc) {
if (rcColorBuffer) rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
if (rcSurface) rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
}
}
EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
{
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcSurface = rcEnc->rcCreateWindowSurface(rcEnc, (uintptr_t)config,
getWidth(), getHeight());
if (!rcSurface) {
ALOGE("rcCreateWindowSurface returned 0");
return EGL_FALSE;
}
rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
pixelFormat);
if (!rcColorBuffer) {
ALOGE("rcCreateColorBuffer returned 0");
return EGL_FALSE;
}
rcEnc->rcSetWindowColorBuffer(rcEnc, rcSurface, rcColorBuffer);
return EGL_TRUE;
}
egl_pbuffer_surface_t* egl_pbuffer_surface_t::create(EGLDisplay dpy,
EGLConfig config, EGLint surfType, int32_t w, int32_t h,
GLenum pixelFormat)
{
egl_pbuffer_surface_t* pb = new egl_pbuffer_surface_t(dpy, config, surfType,
w, h);
if (pb && !pb->init(pixelFormat)) {
delete pb;
pb = NULL;
}
return pb;
}
static const char *getGLString(int glEnum)
{
EGLThreadInfo *tInfo = getEGLThreadInfo();
if (!tInfo || !tInfo->currentContext) {
return NULL;
}
const char** strPtr = NULL;
#define GL_VENDOR 0x1F00
#define GL_RENDERER 0x1F01
#define GL_VERSION 0x1F02
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
#define GL_EXTENSIONS 0x1F03
switch(glEnum) {
case GL_VERSION:
strPtr = &tInfo->currentContext->versionString;
break;
case GL_VENDOR:
strPtr = &tInfo->currentContext->vendorString;
break;
case GL_RENDERER:
strPtr = &tInfo->currentContext->rendererString;
break;
case GL_SHADING_LANGUAGE_VERSION:
strPtr = &tInfo->currentContext->shaderVersionString;
break;
case GL_EXTENSIONS:
strPtr = &tInfo->currentContext->extensionString;
break;
}
if (!strPtr) {
return NULL;
}
if (*strPtr != NULL) {
//
// string is already cached
//
return *strPtr;
}
//
// first query of that string - need to query host
//
DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
char *hostStr = NULL;
int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
if (n < 0) {
hostStr = new char[-n+1];
n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
if (n <= 0) {
delete [] hostStr;
hostStr = NULL;
}
}
//
// keep the string in the context and return its value
//
*strPtr = hostStr;
return hostStr;
}
// ----------------------------------------------------------------------------
// The one and only supported display object.
static eglDisplay s_display;
static EGLClient_eglInterface s_eglIface = {
getThreadInfo: getEGLThreadInfo,
getGLString: getGLString
};
#define DBG_FUNC DBG("%s\n", __FUNCTION__)
EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id)
{
//
// we support only EGL_DEFAULT_DISPLAY.
//
if (display_id != EGL_DEFAULT_DISPLAY) {
return EGL_NO_DISPLAY;
}
return (EGLDisplay)&s_display;
}
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
VALIDATE_DISPLAY(dpy,EGL_FALSE);
if (!s_display.initialize(&s_eglIface)) {
return EGL_FALSE;
}
if (major!=NULL)
*major = s_display.getVersionMajor();
if (minor!=NULL)
*minor = s_display.getVersionMinor();
return EGL_TRUE;
}
EGLBoolean eglTerminate(EGLDisplay dpy)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
s_display.terminate();
return EGL_TRUE;
}
EGLint eglGetError()
{
EGLint error = getEGLThreadInfo()->eglError;
getEGLThreadInfo()->eglError = EGL_SUCCESS;
return error;
}
__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
{
// search in EGL function table
for (int i=0; i<egl_num_funcs; i++) {
if (!strcmp(egl_funcs_by_name[i].name, procname)) {
return (__eglMustCastToProperFunctionPointerType)egl_funcs_by_name[i].proc;
}
}
// look in gles client api's extensions table
return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname);
// Fail - function not found.
return NULL;
}
const char* eglQueryString(EGLDisplay dpy, EGLint name)
{
VALIDATE_DISPLAY_INIT(dpy, NULL);
return s_display.queryString(name);
}
EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
{
VALIDATE_DISPLAY_INIT(dpy, NULL);
if(!num_config) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
}
GLint numConfigs = s_display.getNumConfigs();
if (!configs) {
*num_config = numConfigs;
return EGL_TRUE;
}
uintptr_t i=0;
for (i=0 ; i<numConfigs && i<config_size ; i++) {
*configs++ = (EGLConfig)i;
}
*num_config = i;
return EGL_TRUE;
}
EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
int attribs_size = 0;
if (attrib_list) {
const EGLint * attrib_p = attrib_list;
while (attrib_p[0] != EGL_NONE) {
attribs_size += 2;
attrib_p += 2;
}
attribs_size++; //for the terminating EGL_NONE
}
uint32_t* tempConfigs[config_size];
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
*num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size * sizeof(EGLint), (uint32_t*)tempConfigs, config_size);
if (configs!=NULL) {
EGLint i=0;
for (i=0;i<(*num_config);i++) {
*((uintptr_t*)configs+i) = *((uint32_t*)tempConfigs+i);
}
}
if (*num_config <= 0)
return EGL_FALSE;
return EGL_TRUE;
}
EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
{
VALIDATE_DISPLAY_INIT(dpy, NULL);
VALIDATE_CONFIG(config, EGL_FALSE);
if (s_display.getConfigAttrib(config, attribute, value))
{
return EGL_TRUE;
}
else
{
RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
}
}
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
{
VALIDATE_DISPLAY_INIT(dpy, NULL);
VALIDATE_CONFIG(config, EGL_FALSE);
if (win == 0) {
setErrorReturn(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)) {
setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
if (static_cast<ANativeWindow*>(win)->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
setErrorReturn(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
}
egl_surface_t* surface = egl_window_surface_t::create(
&s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
if (!surface) {
setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
return surface;
}
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
{
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)) {
setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
int32_t w = 0;
int32_t h = 0;
EGLint texFormat = EGL_NO_TEXTURE;
EGLint texTarget = EGL_NO_TEXTURE;
while (attrib_list[0]) {
switch (attrib_list[0]) {
case EGL_WIDTH:
w = attrib_list[1];
break;
case EGL_HEIGHT:
h = attrib_list[1];
break;
case EGL_TEXTURE_FORMAT:
texFormat = attrib_list[1];
break;
case EGL_TEXTURE_TARGET:
texTarget = attrib_list[1];
break;
default:
break;
};
attrib_list+=2;
}
if (((texFormat == EGL_NO_TEXTURE)&&(texTarget != EGL_NO_TEXTURE)) ||
((texFormat != EGL_NO_TEXTURE)&&(texTarget == EGL_NO_TEXTURE))) {
setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
}
// TODO: check EGL_TEXTURE_FORMAT - need to support eglBindTexImage
GLenum pixelFormat;
if (s_display.getConfigGLPixelFormat(config, &pixelFormat) == EGL_FALSE)
setErrorReturn(EGL_BAD_MATCH, EGL_NO_SURFACE);
egl_surface_t* surface = egl_pbuffer_surface_t::create(dpy, config,
surfaceType, w, h, pixelFormat);
if (!surface) {
setErrorReturn(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
//setup attributes
surface->setTextureFormat(texFormat);
surface->setTextureTarget(texTarget);
return surface;
}
EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
{
//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 eglSurface)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
delete surface;
return EGL_TRUE;
}
EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
egl_surface_t* surface( static_cast<egl_surface_t*>(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;
case EGL_TEXTURE_FORMAT:
*value = surface->getTextureFormat();
break;
case EGL_TEXTURE_TARGET:
*value = surface->getTextureTarget();
break;
case EGL_SWAP_BEHAVIOR:
*value = surface->getSwapBehavior();
break;
case EGL_LARGEST_PBUFFER:
// not modified for a window or pixmap surface
// and we ignore it when creating a PBuffer surface (default is EGL_FALSE)
if (surface->getSurfaceType() & EGL_PBUFFER_BIT) *value = EGL_FALSE;
break;
//TODO: complete other attributes
default:
ALOGE("eglQuerySurface %x EGL_BAD_ATTRIBUTE", attribute);
ret = setErrorFunc(EGL_BAD_ATTRIBUTE, EGL_FALSE);
break;
}
return ret;
}
EGLBoolean eglBindAPI(EGLenum api)
{
if (api != EGL_OPENGL_ES_API)
setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
return EGL_TRUE;
}
EGLenum eglQueryAPI()
{
return EGL_OPENGL_ES_API;
}
EGLBoolean eglWaitClient()
{
return eglWaitGL();
}
EGLBoolean eglReleaseThread()
{
EGLThreadInfo *tInfo = getEGLThreadInfo();
if (tInfo && tInfo->currentContext) {
return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
}
return EGL_TRUE;
}
EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
{
//TODO
ALOGW("%s not implemented", __FUNCTION__);
return 0;
}
EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
{
//TODO
ALOGW("%s not implemented", __FUNCTION__);
return 0;
}
EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
if (eglSurface == EGL_NO_SURFACE) {
setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
}
if (buffer != EGL_BACK_BUFFER) {
setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
}
egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
}
if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
}
//It's now safe to cast to pbuffer surface
egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
return GL_TRUE;
}
EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
//TODO
ALOGW("%s not implemented", __FUNCTION__);
return 0;
}
EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
EGLContext_t* ctx = getEGLThreadInfo()->currentContext;
if (!ctx) {
setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
}
if (!ctx->draw) {
setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
}
egl_surface_t* draw(static_cast<egl_surface_t*>(ctx->draw));
draw->setSwapInterval(interval);
rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
return EGL_TRUE;
}
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
EGLint version = 1; //default
while (attrib_list && attrib_list[0]) {
if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) version = attrib_list[1];
attrib_list+=2;
}
uint32_t rcShareCtx = 0;
EGLContext_t * shareCtx = NULL;
if (share_context) {
shareCtx = static_cast<EGLContext_t*>(share_context);
rcShareCtx = shareCtx->rcContext;
if (shareCtx->dpy != dpy)
setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
}
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
if (!rcContext) {
ALOGE("rcCreateContext returned 0");
setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
}
EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
if (!context)
setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
context->version = version;
context->rcContext = rcContext;
return context;
}
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
if (!context) return EGL_TRUE;
if (getEGLThreadInfo()->currentContext == context) {
getEGLThreadInfo()->currentContext->deletePending = 1;
return EGL_TRUE;
}
if (context->rcContext) {
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcEnc->rcDestroyContext(rcEnc, context->rcContext);
context->rcContext = 0;
}
delete context;
return EGL_TRUE;
}
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_SURFACE_RETURN(draw, EGL_FALSE);
VALIDATE_SURFACE_RETURN(read, EGL_FALSE);
if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
setErrorReturn(EGL_BAD_MATCH, EGL_FALSE);
EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
uint32_t ctxHandle = (context) ? context->rcContext : 0;
egl_surface_t * drawSurf = static_cast<egl_surface_t *>(draw);
uint32_t drawHandle = (drawSurf) ? drawSurf->getRcSurface() : 0;
egl_surface_t * readSurf = static_cast<egl_surface_t *>(read);
uint32_t readHandle = (readSurf) ? readSurf->getRcSurface() : 0;
//
// Nothing to do if no binding change has made
//
EGLThreadInfo *tInfo = getEGLThreadInfo();
if (tInfo->currentContext == context &&
(context == NULL ||
(context && context->draw == draw && context->read == read))) {
return EGL_TRUE;
}
if (tInfo->currentContext && tInfo->currentContext->deletePending) {
if (tInfo->currentContext != context) {
EGLContext_t * contextToDelete = tInfo->currentContext;
tInfo->currentContext = 0;
eglDestroyContext(dpy, contextToDelete);
}
}
if (context && (context->flags & EGLContext_t::IS_CURRENT) && (context != tInfo->currentContext)) {
//context is current to another thread
setErrorReturn(EGL_BAD_ACCESS, EGL_FALSE);
}
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
if (rcEnc->rcMakeCurrent(rcEnc, ctxHandle, drawHandle, readHandle) == EGL_FALSE) {
ALOGE("rcMakeCurrent returned EGL_FALSE");
setErrorReturn(EGL_BAD_CONTEXT, EGL_FALSE);
}
//Now make the local bind
if (context) {
context->draw = draw;
context->read = read;
context->flags |= EGLContext_t::IS_CURRENT;
//set the client state
if (context->version == 2) {
hostCon->gl2Encoder()->setClientState(context->getClientState());
hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
}
else {
hostCon->glEncoder()->setClientState(context->getClientState());
hostCon->glEncoder()->setSharedGroup(context->getSharedGroup());
}
}
else if (tInfo->currentContext) {
//release ClientState & SharedGroup
if (tInfo->currentContext->version == 2) {
hostCon->gl2Encoder()->setClientState(NULL);
hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
}
else {
hostCon->glEncoder()->setClientState(NULL);
hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL));
}
}
if (tInfo->currentContext)
tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
//Now make current
tInfo->currentContext = context;
//Check maybe we need to init the encoder, if it's first eglMakeCurrent
if (tInfo->currentContext) {
if (tInfo->currentContext->version == 2) {
if (!hostCon->gl2Encoder()->isInitialized()) {
s_display.gles2_iface()->init();
hostCon->gl2Encoder()->setInitialized();
ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
}
}
else {
if (!hostCon->glEncoder()->isInitialized()) {
s_display.gles_iface()->init();
hostCon->glEncoder()->setInitialized();
ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0);
}
}
}
return EGL_TRUE;
}
EGLContext eglGetCurrentContext()
{
return getEGLThreadInfo()->currentContext;
}
EGLSurface eglGetCurrentSurface(EGLint readdraw)
{
EGLContext_t * context = getEGLThreadInfo()->currentContext;
if (!context)
return EGL_NO_SURFACE; //not an error
switch (readdraw) {
case EGL_READ:
return context->read;
case EGL_DRAW:
return context->draw;
default:
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
}
}
EGLDisplay eglGetCurrentDisplay()
{
EGLContext_t * context = getEGLThreadInfo()->currentContext;
if (!context)
return EGL_NO_DISPLAY; //not an error
return context->dpy;
}
EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_CONTEXT_RETURN(ctx, EGL_FALSE);
EGLContext_t * context = static_cast<EGLContext_t*>(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:
ALOGE("eglQueryContext %x EGL_BAD_ATTRIBUTE", attribute);
setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
break;
}
return ret;
}
EGLBoolean eglWaitGL()
{
EGLThreadInfo *tInfo = getEGLThreadInfo();
if (!tInfo || !tInfo->currentContext) {
return EGL_FALSE;
}
if (tInfo->currentContext->version == 2) {
s_display.gles2_iface()->finish();
}
else {
s_display.gles_iface()->finish();
}
return EGL_TRUE;
}
EGLBoolean eglWaitNative(EGLint engine)
{
return EGL_TRUE;
}
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface eglSurface)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
if (eglSurface == EGL_NO_SURFACE)
setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
egl_surface_t* d = static_cast<egl_surface_t*>(eglSurface);
if (d->dpy != dpy)
setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
// post the surface
d->swapBuffers();
hostCon->flush();
return EGL_TRUE;
}
EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
{
//TODO :later
return 0;
}
EGLBoolean eglLockSurfaceKHR(EGLDisplay display, EGLSurface surface, const EGLint *attrib_list)
{
//TODO later
return 0;
}
EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface)
{
//TODO later
return 0;
}
EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR);
if (ctx != EGL_NO_CONTEXT) {
setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
}
if (target != EGL_NATIVE_BUFFER_ANDROID) {
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
}
android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
if (native_buffer->common.version != sizeof(android_native_buffer_t))
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
switch (cb->format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_BGRA_8888:
case HAL_PIXEL_FORMAT_RGBA_5551:
case HAL_PIXEL_FORMAT_RGBA_4444:
break;
default:
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
}
native_buffer->common.incRef(&native_buffer->common);
return (EGLImageKHR)native_buffer;
}
EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
{
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
if (native_buffer->common.version != sizeof(android_native_buffer_t))
setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
native_buffer->common.decRef(&native_buffer->common);
return EGL_TRUE;
}
#define FENCE_SYNC_HANDLE (EGLSyncKHR)0xFE4CE
EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type,
const EGLint *attrib_list)
{
// TODO: This implementation could be faster. We should require the host EGL
// to support KHR_fence_sync, or at least pipe the fence command to the host
// and wait for it (probably involving a glFinish on the host) in
// eglClientWaitSyncKHR.
VALIDATE_DISPLAY(dpy, EGL_NO_SYNC_KHR);
if (type != EGL_SYNC_FENCE_KHR ||
(attrib_list != NULL && attrib_list[0] != EGL_NONE)) {
setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
}
EGLThreadInfo *tInfo = getEGLThreadInfo();
if (!tInfo || !tInfo->currentContext) {
setErrorReturn(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
}
if (tInfo->currentContext->version == 2) {
s_display.gles2_iface()->finish();
} else {
s_display.gles_iface()->finish();
}
return FENCE_SYNC_HANDLE;
}
EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
{
if (sync != FENCE_SYNC_HANDLE) {
setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
}
return EGL_TRUE;
}
EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags,
EGLTimeKHR timeout)
{
if (sync != FENCE_SYNC_HANDLE) {
setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
}
return EGL_CONDITION_SATISFIED_KHR;
}
EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
EGLint attribute, EGLint *value)
{
if (sync != FENCE_SYNC_HANDLE) {
setErrorReturn(EGL_BAD_PARAMETER, EGL_FALSE);
}
switch (attribute) {
case EGL_SYNC_TYPE_KHR:
*value = EGL_SYNC_FENCE_KHR;
return EGL_TRUE;
case EGL_SYNC_STATUS_KHR:
*value = EGL_SIGNALED_KHR;
return EGL_TRUE;
case EGL_SYNC_CONDITION_KHR:
*value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
return EGL_TRUE;
default:
setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_FALSE);
}
}