egl.cpp revision 0a3139a21e628093893bba8ca0bb0b4742e0522c
1326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams/* 2326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** 3326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** Copyright 2007 The Android Open Source Project 4326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** 5326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** Licensed under the Apache License Version 2.0(the "License"); 6326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** you may not use this file except in compliance with the License. 7326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** You may obtain a copy of the License at 8326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** 9326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** http://www.apache.org/licenses/LICENSE-2.0 10326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** 11326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** Unless required by applicable law or agreed to in writing software 12326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** distributed under the License is distributed on an "AS IS" BASIS 13326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. 14326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** See the License for the specific language governing permissions and 15326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** limitations under the License. 16326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams*/ 17326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 18326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <assert.h> 19326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <errno.h> 20326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <stdlib.h> 21326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <stdio.h> 22326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <string.h> 23326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <unistd.h> 24326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <fcntl.h> 25326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <sys/ioctl.h> 26326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <sys/types.h> 27326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <sys/mman.h> 28326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 29326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <cutils/log.h> 30326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <cutils/atomic.h> 31326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 32326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <utils/threads.h> 33326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 34326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <EGL/egl.h> 35326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <EGL/eglext.h> 36326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <GLES/gl.h> 37326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <GLES/glext.h> 38326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 39326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <pixelflinger/format.h> 40326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <pixelflinger/pixelflinger.h> 41326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 42326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <private/ui/android_natives_priv.h> 43326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 44326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "context.h" 45326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "state.h" 46326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "texture.h" 47326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "matrix.h" 48326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 49326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#ifdef LIBAGL_USE_GRALLOC_COPYBITS 50326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "gralloc_priv.h" 51326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#endif // LIBAGL_USE_GRALLOC_COPYBITS 52326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 53326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#undef NELEM 54326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#define NELEM(x) (sizeof(x)/sizeof(*(x))) 55326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 56326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams// ---------------------------------------------------------------------------- 57326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsnamespace android { 58326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams// ---------------------------------------------------------------------------- 59326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 60a44cb29164726cd9d812117819abdd7b60dfdd93Jason Samsconst unsigned int NUM_DISPLAYS = 1; 61326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 62326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstatic pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER; 63326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstatic pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER; 64326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstatic pthread_key_t gEGLErrorKey = -1; 65326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#ifndef HAVE_ANDROID_OS 66326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsnamespace gl { 67a44cb29164726cd9d812117819abdd7b60dfdd93Jason Samspthread_key_t gGLKey = -1; 68326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}; // namespace gl 69326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#endif 70326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 71a44cb29164726cd9d812117819abdd7b60dfdd93Jason Samstemplate<typename T> 72a44cb29164726cd9d812117819abdd7b60dfdd93Jason Samsstatic T setError(GLint error, T returnValue) { 73326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (ggl_unlikely(gEGLErrorKey == -1)) { 74326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams pthread_mutex_lock(&gErrorKeyMutex); 75326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (gEGLErrorKey == -1) 76326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams pthread_key_create(&gEGLErrorKey, NULL); 77326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams pthread_mutex_unlock(&gErrorKeyMutex); 78326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 796678e9b2568ad041429a2477177133fe4932159fJason Sams pthread_setspecific(gEGLErrorKey, (void*)error); 80326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return returnValue; 81326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 82326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 83326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstatic GLint getError() { 84326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (ggl_unlikely(gEGLErrorKey == -1)) 85326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return EGL_SUCCESS; 86326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams GLint error = (GLint)pthread_getspecific(gEGLErrorKey); 87326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS); 88326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return error; 89326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 90326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 91326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams// ---------------------------------------------------------------------------- 92326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 93326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstruct egl_display_t 94326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 95326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams egl_display_t() : type(0), initialized(0) { } 96a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams 97326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams static egl_display_t& get_display(EGLDisplay dpy); 98326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 99326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams static EGLBoolean is_valid(EGLDisplay dpy) { 100326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE; 101326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 102326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 103326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams NativeDisplayType type; 104a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams volatile int32_t initialized; 105326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}; 106326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 107326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstatic egl_display_t gDisplays[NUM_DISPLAYS]; 108326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 109326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsegl_display_t& egl_display_t::get_display(EGLDisplay dpy) { 110326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return gDisplays[uintptr_t(dpy)-1U]; 111326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 112326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 113326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstruct egl_context_t { 114326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams enum { 115326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams IS_CURRENT = 0x00010000, 116326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams NEVER_CURRENT = 0x00020000 117326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams }; 118326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams uint32_t flags; 119326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams EGLDisplay dpy; 120326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams EGLConfig config; 121326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams EGLSurface read; 122326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams EGLSurface draw; 123326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 124326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams static inline egl_context_t* context(EGLContext ctx) { 125326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams ogles_context_t* const gl = static_cast<ogles_context_t*>(ctx); 126326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return static_cast<egl_context_t*>(gl->rasterizer.base); 127326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 128326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}; 129326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 130326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams// ---------------------------------------------------------------------------- 131326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 132326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstruct egl_surface_t 133326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 134326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams enum { 135326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams PAGE_FLIP = 0x00000001, 136326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams MAGIC = 0x31415265 137a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams }; 138326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 139a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams uint32_t magic; 140326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams EGLDisplay dpy; 141a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams EGLConfig config; 142a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams EGLContext ctx; 143326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 144326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat); 145326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual ~egl_surface_t(); 146326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual bool isValid() const = 0; 147a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams 148a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0; 149326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0; 150326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual void connect() {} 151326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual void disconnect() {} 152326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getWidth() const = 0; 153326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getHeight() const = 0; 154326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 155326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getHorizontalResolution() const; 156326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getVerticalResolution() const; 157326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getRefreshRate() const; 158326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getSwapBehavior() const; 159326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLBoolean swapBuffers(); 160326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); 161326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsprotected: 162326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams GGLSurface depth; 163326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}; 164326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 165326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsegl_surface_t::egl_surface_t(EGLDisplay dpy, 166326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams EGLConfig config, 167326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams int32_t depthFormat) 168326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams : magic(MAGIC), dpy(dpy), config(config), ctx(0) 169326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 170326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams depth.version = sizeof(GGLSurface); 171326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams depth.data = 0; 172326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams depth.format = depthFormat; 173326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 174326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsegl_surface_t::~egl_surface_t() 175a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams{ 176a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams magic = 0; 177a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams free(depth.data); 178a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams} 179a658e905f14fe500bfee3812b213a73cb37ef6f2Jason SamsEGLBoolean egl_surface_t::swapBuffers() { 180a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams return EGL_FALSE; 181a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams} 182a658e905f14fe500bfee3812b213a73cb37ef6f2Jason SamsEGLint egl_surface_t::getHorizontalResolution() const { 183a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 184a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams} 185a658e905f14fe500bfee3812b213a73cb37ef6f2Jason SamsEGLint egl_surface_t::getVerticalResolution() const { 186a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 187a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams} 188a658e905f14fe500bfee3812b213a73cb37ef6f2Jason SamsEGLint egl_surface_t::getRefreshRate() const { 189326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return (60 * EGL_DISPLAY_SCALING); 190326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 191326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsEGLint egl_surface_t::getSwapBehavior() const { 192326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return EGL_BUFFER_PRESERVED; 193326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 194326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsEGLBoolean egl_surface_t::setSwapRectangle( 195326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams EGLint l, EGLint t, EGLint w, EGLint h) 196326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 197326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return EGL_FALSE; 198326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 199326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 200a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams// ---------------------------------------------------------------------------- 201326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 202326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsstruct egl_window_surface_v2_t : public egl_surface_t 203326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 204326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams egl_window_surface_v2_t( 205326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams EGLDisplay dpy, EGLConfig config, 206326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams int32_t depthFormat, 207326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams android_native_window_t* window); 208326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 209326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams ~egl_window_surface_v2_t(); 210326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 211326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual bool isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; } 212326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLBoolean swapBuffers(); 213326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); 214326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLBoolean bindReadSurface(ogles_context_t* gl); 215326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual void connect(); 216326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual void disconnect(); 217326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getWidth() const { return buffer->width; } 218326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getHeight() const { return buffer->height; } 219326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getHorizontalResolution() const; 220326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getVerticalResolution() const; 221326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getRefreshRate() const; 222326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLint getSwapBehavior() const; 223326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); 224326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 225326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsprivate: 226326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams status_t lock(android_native_buffer_t* buf, int usage, void** vaddr); 227326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams status_t unlock(android_native_buffer_t* buf); 228326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams android_native_window_t* nativeWindow; 229326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams android_native_buffer_t* buffer; 230326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams android_native_buffer_t* previousBuffer; 231326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams gralloc_module_t const* module; 232326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams int width; 233326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams int height; 234326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams void* bits; 235326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams GGLFormat const* pixelFormatTable; 236326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 237326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams struct Rect { 238326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams inline Rect() { }; 239326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams inline Rect(int32_t w, int32_t h) 240326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams : left(0), top(0), right(w), bottom(h) { } 241326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) 242326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams : left(l), top(t), right(r), bottom(b) { } 243326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Rect& andSelf(const Rect& r) { 244326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams left = max(left, r.left); 245326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams top = max(top, r.top); 246326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams right = min(right, r.right); 247326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams bottom = min(bottom, r.bottom); 248326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return *this; 249326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 250326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams bool isEmpty() const { 251326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return (left>=right || top>=bottom); 252326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 253a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams void dump(char const* what) { 254326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams LOGD("%s { %5d, %5d, w=%5d, h=%5d }", 255326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams what, left, top, right-left, bottom-top); 256326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 257326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 258326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams int32_t left; 259326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams int32_t top; 260326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams int32_t right; 261326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams int32_t bottom; 262326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams }; 263326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 264326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams struct Region { 265326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams inline Region() : count(0) { } 266326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams static Region subtract(const Rect& lhs, const Rect& rhs) { 267326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Region reg; 268326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Rect* storage = reg.storage; 269326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (!lhs.isEmpty()) { 270326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (lhs.top < rhs.top) { // top rect 271326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->left = lhs.left; 272326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->top = lhs.top; 273326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->right = lhs.right; 274326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->bottom = max(lhs.top, rhs.top); 275326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage++; 276326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 277326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (lhs.left < rhs.left) { // left-side rect 278326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->left = lhs.left; 279326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->top = max(lhs.top, rhs.top); 280326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->right = max(lhs.left, rhs.left); 281326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->bottom = min(lhs.bottom, rhs.bottom); 282326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage++; 283326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 284326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (lhs.right > rhs.right) { // right-side rect 285326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->left = min(lhs.right, rhs.right); 286326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->top = max(lhs.top, rhs.top); 287326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->right = lhs.right; 288326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->bottom = min(lhs.bottom, rhs.bottom); 289326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage++; 290326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 291326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (lhs.bottom > rhs.bottom) { // bottom rect 292326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->left = lhs.left; 293326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->top = min(lhs.bottom, rhs.bottom); 294326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->right = lhs.right; 295326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage->bottom = lhs.bottom; 296326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams storage++; 297326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 298326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams reg.count = storage - reg.storage; 299326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 300326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return reg; 301326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 302326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams bool isEmpty() const { 303326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return count<=0; 304326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 305326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams ssize_t getRects(Rect const* * rects) const { 306326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *rects = storage; 307326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return count; 308326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 309326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams private: 310326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Rect storage[4]; 311326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams ssize_t count; 312326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams }; 313326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 314 void copyBlt( 315 android_native_buffer_t* dst, void* dst_vaddr, 316 android_native_buffer_t* src, void const* src_vaddr, 317 const Rect* reg, ssize_t count); 318 319 Rect dirtyRegion; 320 Rect oldDirtyRegion; 321}; 322 323egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, 324 EGLConfig config, 325 int32_t depthFormat, 326 android_native_window_t* window) 327 : egl_surface_t(dpy, config, depthFormat), 328 nativeWindow(window), buffer(0), previousBuffer(0), module(0), 329 bits(NULL) 330{ 331 hw_module_t const* pModule; 332 hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); 333 module = reinterpret_cast<gralloc_module_t const*>(pModule); 334 335 pixelFormatTable = gglGetPixelFormatTable(); 336 337 // keep a reference on the window 338 nativeWindow->common.incRef(&nativeWindow->common); 339 340 // dequeue a buffer 341 nativeWindow->dequeueBuffer(nativeWindow, &buffer); 342 343 // allocate a corresponding depth-buffer 344 width = buffer->width; 345 height = buffer->height; 346 if (depthFormat) { 347 depth.width = width; 348 depth.height = height; 349 depth.stride = depth.width; // use the width here 350 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 351 if (depth.data == 0) { 352 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 353 return; 354 } 355 } 356 357 // keep a reference on the buffer 358 buffer->common.incRef(&buffer->common); 359} 360 361egl_window_surface_v2_t::~egl_window_surface_v2_t() { 362 if (buffer) { 363 buffer->common.decRef(&buffer->common); 364 } 365 if (previousBuffer) { 366 previousBuffer->common.decRef(&previousBuffer->common); 367 } 368 nativeWindow->common.decRef(&nativeWindow->common); 369} 370 371void egl_window_surface_v2_t::connect() 372{ 373 // Lock the buffer 374 nativeWindow->lockBuffer(nativeWindow, buffer); 375 // pin the buffer down 376 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | 377 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { 378 LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", 379 buffer, buffer->width, buffer->height); 380 setError(EGL_BAD_ACCESS, EGL_NO_SURFACE); 381 // FIXME: we should make sure we're not accessing the buffer anymore 382 } 383} 384 385void egl_window_surface_v2_t::disconnect() 386{ 387 if (buffer && bits) { 388 bits = NULL; 389 unlock(buffer); 390 } 391} 392 393status_t egl_window_surface_v2_t::lock( 394 android_native_buffer_t* buf, int usage, void** vaddr) 395{ 396 int err = module->lock(module, buf->handle, 397 usage, 0, 0, buf->width, buf->height, vaddr); 398 return err; 399} 400 401status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) 402{ 403 int err = module->unlock(module, buf->handle); 404 return err; 405} 406 407void egl_window_surface_v2_t::copyBlt( 408 android_native_buffer_t* dst, void* dst_vaddr, 409 android_native_buffer_t* src, void const* src_vaddr, 410 const Rect* reg, ssize_t count) 411{ 412 // FIXME: use copybit if possible 413 // NOTE: dst and src must be the same format 414 415 Rect r; 416 const size_t bpp = pixelFormatTable[src->format].size; 417 const size_t dbpr = dst->stride * bpp; 418 const size_t sbpr = src->stride * bpp; 419 420 uint8_t const * const src_bits = (uint8_t const *)src_vaddr; 421 uint8_t * const dst_bits = (uint8_t *)dst_vaddr; 422 423 for (int i= 0 ; i<count ; i++) { 424 const Rect& r(reg[i]); 425 ssize_t w = r.right - r.left; 426 ssize_t h = r.bottom - r.top; 427 if (w <= 0 || h<=0) continue; 428 size_t size = w * bpp; 429 uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; 430 uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; 431 if (dbpr==sbpr && size==sbpr) { 432 size *= h; 433 h = 1; 434 } 435 do { 436 memcpy(d, s, size); 437 d += dbpr; 438 s += sbpr; 439 } while (--h > 0); 440 } 441} 442 443EGLBoolean egl_window_surface_v2_t::swapBuffers() 444{ 445 /* 446 * Handle eglSetSwapRectangleANDROID() 447 * We copyback from the front buffer 448 */ 449 if (!dirtyRegion.isEmpty()) { 450 dirtyRegion.andSelf(Rect(buffer->width, buffer->height)); 451 if (previousBuffer) { 452 const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion)); 453 if (!copyBack.isEmpty()) { 454 Rect const* list; 455 ssize_t count = copyBack.getRects(&list); 456 // copy from previousBuffer to buffer 457 void* prevBits; 458 if (lock(previousBuffer, 459 GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) 460 { 461 copyBlt(buffer, bits, previousBuffer, prevBits, list, count); 462 unlock(previousBuffer); 463 } 464 } 465 } 466 oldDirtyRegion = dirtyRegion; 467 } 468 469 if (previousBuffer) { 470 previousBuffer->common.decRef(&previousBuffer->common); 471 previousBuffer = 0; 472 } 473 474 unlock(buffer); 475 previousBuffer = buffer; 476 nativeWindow->queueBuffer(nativeWindow, buffer); 477 buffer = 0; 478 479 // dequeue a new buffer 480 nativeWindow->dequeueBuffer(nativeWindow, &buffer); 481 482 // TODO: lockBuffer should rather be executed when the very first 483 // direct rendering occurs. 484 nativeWindow->lockBuffer(nativeWindow, buffer); 485 486 // reallocate the depth-buffer if needed 487 if ((width != buffer->width) || (height != buffer->height)) { 488 // TODO: we probably should reset the swap rect here 489 // if the window size has changed 490 width = buffer->width; 491 height = buffer->height; 492 if (depth.data) { 493 free(depth.data); 494 depth.width = width; 495 depth.height = height; 496 depth.stride = buffer->stride; 497 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 498 if (depth.data == 0) { 499 setError(EGL_BAD_ALLOC, EGL_FALSE); 500 return EGL_FALSE; 501 } 502 } 503 } 504 505 // keep a reference on the buffer 506 buffer->common.incRef(&buffer->common); 507 508 // finally pin the buffer down 509 if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | 510 GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { 511 LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", 512 buffer, buffer->width, buffer->height); 513 setError(EGL_BAD_ACCESS, EGL_NO_SURFACE); 514 // FIXME: we should make sure we're not accessing the buffer anymore 515 } 516 517 return EGL_TRUE; 518} 519 520EGLBoolean egl_window_surface_v2_t::setSwapRectangle( 521 EGLint l, EGLint t, EGLint w, EGLint h) 522{ 523 dirtyRegion = Rect(l, t, l+w, t+h); 524 return EGL_TRUE; 525} 526 527#ifdef LIBAGL_USE_GRALLOC_COPYBITS 528 529static bool supportedCopybitsDestinationFormat(int format) { 530 // Hardware supported and no destination alpha 531 switch (format) { 532 case HAL_PIXEL_FORMAT_RGB_565: 533 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 534 case HAL_PIXEL_FORMAT_YCbCr_420_SP: 535 return true; 536 default: 537 return false; 538 } 539} 540#endif 541 542EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) 543{ 544 GGLSurface buffer; 545 buffer.version = sizeof(GGLSurface); 546 buffer.width = this->buffer->width; 547 buffer.height = this->buffer->height; 548 buffer.stride = this->buffer->stride; 549 buffer.data = (GGLubyte*)bits; 550 buffer.format = this->buffer->format; 551 gl->rasterizer.procs.colorBuffer(gl, &buffer); 552 if (depth.data != gl->rasterizer.state.buffers.depth.data) 553 gl->rasterizer.procs.depthBuffer(gl, &depth); 554 555#ifdef LIBAGL_USE_GRALLOC_COPYBITS 556 gl->copybits.drawSurfaceBuffer = 0; 557 if (supportedCopybitsDestinationFormat(buffer.format)) { 558 buffer_handle_t handle = this->buffer->handle; 559 if (handle != NULL) { 560 private_handle_t* hand = private_handle_t::dynamicCast(handle); 561 if (hand != NULL && hand->usesPhysicallyContiguousMemory()) { 562 gl->copybits.drawSurfaceBuffer = handle; 563 } 564 } 565 } 566#endif // LIBAGL_USE_GRALLOC_COPYBITS 567 568 return EGL_TRUE; 569} 570EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl) 571{ 572 GGLSurface buffer; 573 buffer.version = sizeof(GGLSurface); 574 buffer.width = this->buffer->width; 575 buffer.height = this->buffer->height; 576 buffer.stride = this->buffer->stride; 577 buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!! 578 buffer.format = this->buffer->format; 579 gl->rasterizer.procs.readBuffer(gl, &buffer); 580 return EGL_TRUE; 581} 582EGLint egl_window_surface_v2_t::getHorizontalResolution() const { 583 return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 584} 585EGLint egl_window_surface_v2_t::getVerticalResolution() const { 586 return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); 587} 588EGLint egl_window_surface_v2_t::getRefreshRate() const { 589 return (60 * EGL_DISPLAY_SCALING); // FIXME 590} 591EGLint egl_window_surface_v2_t::getSwapBehavior() const 592{ 593 /* 594 * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves 595 * the content of the swapped buffer. 596 * 597 * EGL_BUFFER_DESTROYED means that the content of the buffer is lost. 598 * 599 * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED 600 * only applies to the area specified by eglSetSwapRectangleANDROID(), that 601 * is, everything outside of this area is preserved. 602 * 603 * This implementation of EGL assumes the later case. 604 * 605 */ 606 607 return EGL_BUFFER_DESTROYED; 608} 609 610// ---------------------------------------------------------------------------- 611 612struct egl_pixmap_surface_t : public egl_surface_t 613{ 614 egl_pixmap_surface_t( 615 EGLDisplay dpy, EGLConfig config, 616 int32_t depthFormat, 617 egl_native_pixmap_t const * pixmap); 618 619 virtual ~egl_pixmap_surface_t() { } 620 621 virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } 622 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); 623 virtual EGLBoolean bindReadSurface(ogles_context_t* gl); 624 virtual EGLint getWidth() const { return nativePixmap.width; } 625 virtual EGLint getHeight() const { return nativePixmap.height; } 626private: 627 egl_native_pixmap_t nativePixmap; 628}; 629 630egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy, 631 EGLConfig config, 632 int32_t depthFormat, 633 egl_native_pixmap_t const * pixmap) 634 : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap) 635{ 636 if (depthFormat) { 637 depth.width = pixmap->width; 638 depth.height = pixmap->height; 639 depth.stride = depth.width; // use the width here 640 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 641 if (depth.data == 0) { 642 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 643 return; 644 } 645 } 646} 647EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl) 648{ 649 GGLSurface buffer; 650 buffer.version = sizeof(GGLSurface); 651 buffer.width = nativePixmap.width; 652 buffer.height = nativePixmap.height; 653 buffer.stride = nativePixmap.stride; 654 buffer.data = nativePixmap.data; 655 buffer.format = nativePixmap.format; 656 657 gl->rasterizer.procs.colorBuffer(gl, &buffer); 658 if (depth.data != gl->rasterizer.state.buffers.depth.data) 659 gl->rasterizer.procs.depthBuffer(gl, &depth); 660 return EGL_TRUE; 661} 662EGLBoolean egl_pixmap_surface_t::bindReadSurface(ogles_context_t* gl) 663{ 664 GGLSurface buffer; 665 buffer.version = sizeof(GGLSurface); 666 buffer.width = nativePixmap.width; 667 buffer.height = nativePixmap.height; 668 buffer.stride = nativePixmap.stride; 669 buffer.data = nativePixmap.data; 670 buffer.format = nativePixmap.format; 671 gl->rasterizer.procs.readBuffer(gl, &buffer); 672 return EGL_TRUE; 673} 674 675// ---------------------------------------------------------------------------- 676 677struct egl_pbuffer_surface_t : public egl_surface_t 678{ 679 egl_pbuffer_surface_t( 680 EGLDisplay dpy, EGLConfig config, int32_t depthFormat, 681 int32_t w, int32_t h, int32_t f); 682 683 virtual ~egl_pbuffer_surface_t(); 684 685 virtual bool isValid() const { return pbuffer.data != 0; } 686 virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); 687 virtual EGLBoolean bindReadSurface(ogles_context_t* gl); 688 virtual EGLint getWidth() const { return pbuffer.width; } 689 virtual EGLint getHeight() const { return pbuffer.height; } 690private: 691 GGLSurface pbuffer; 692}; 693 694egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, 695 EGLConfig config, int32_t depthFormat, 696 int32_t w, int32_t h, int32_t f) 697 : egl_surface_t(dpy, config, depthFormat) 698{ 699 size_t size = w*h; 700 switch (f) { 701 case GGL_PIXEL_FORMAT_A_8: size *= 1; break; 702 case GGL_PIXEL_FORMAT_RGB_565: size *= 2; break; 703 case GGL_PIXEL_FORMAT_RGBA_8888: size *= 4; break; 704 default: 705 LOGE("incompatible pixel format for pbuffer (format=%d)", f); 706 pbuffer.data = 0; 707 break; 708 } 709 pbuffer.version = sizeof(GGLSurface); 710 pbuffer.width = w; 711 pbuffer.height = h; 712 pbuffer.stride = w; 713 pbuffer.data = (GGLubyte*)malloc(size); 714 pbuffer.format = f; 715 716 if (depthFormat) { 717 depth.width = pbuffer.width; 718 depth.height = pbuffer.height; 719 depth.stride = depth.width; // use the width here 720 depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); 721 if (depth.data == 0) { 722 setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 723 return; 724 } 725 } 726} 727egl_pbuffer_surface_t::~egl_pbuffer_surface_t() { 728 free(pbuffer.data); 729} 730EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(ogles_context_t* gl) 731{ 732 gl->rasterizer.procs.colorBuffer(gl, &pbuffer); 733 if (depth.data != gl->rasterizer.state.buffers.depth.data) 734 gl->rasterizer.procs.depthBuffer(gl, &depth); 735 return EGL_TRUE; 736} 737EGLBoolean egl_pbuffer_surface_t::bindReadSurface(ogles_context_t* gl) 738{ 739 gl->rasterizer.procs.readBuffer(gl, &pbuffer); 740 return EGL_TRUE; 741} 742 743// ---------------------------------------------------------------------------- 744 745struct config_pair_t { 746 GLint key; 747 GLint value; 748}; 749 750struct configs_t { 751 const config_pair_t* array; 752 int size; 753}; 754 755struct config_management_t { 756 GLint key; 757 bool (*match)(GLint reqValue, GLint confValue); 758 static bool atLeast(GLint reqValue, GLint confValue) { 759 return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue); 760 } 761 static bool exact(GLint reqValue, GLint confValue) { 762 return (reqValue == EGL_DONT_CARE) || (confValue == reqValue); 763 } 764 static bool mask(GLint reqValue, GLint confValue) { 765 return (confValue & reqValue) == reqValue; 766 } 767}; 768 769// ---------------------------------------------------------------------------- 770 771#define VERSION_MAJOR 1 772#define VERSION_MINOR 2 773static char const * const gVendorString = "Google Inc."; 774static char const * const gVersionString = "1.2 Android Driver"; 775static char const * const gClientApiString = "OpenGL ES"; 776static char const * const gExtensionsString = 777 "EGL_KHR_image_base " 778 // "KHR_image_pixmap " 779 "EGL_ANDROID_image_native_buffer " 780 "EGL_ANDROID_swap_rectangle " 781 ; 782 783// ---------------------------------------------------------------------------- 784 785struct extention_map_t { 786 const char * const name; 787 __eglMustCastToProperFunctionPointerType address; 788}; 789 790static const extention_map_t gExtentionMap[] = { 791 { "glDrawTexsOES", 792 (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES }, 793 { "glDrawTexiOES", 794 (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES }, 795 { "glDrawTexfOES", 796 (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES }, 797 { "glDrawTexxOES", 798 (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES }, 799 { "glDrawTexsvOES", 800 (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES }, 801 { "glDrawTexivOES", 802 (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES }, 803 { "glDrawTexfvOES", 804 (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES }, 805 { "glDrawTexxvOES", 806 (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES }, 807 { "glQueryMatrixxOES", 808 (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES }, 809 { "glEGLImageTargetTexture2DOES", 810 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES }, 811 { "glEGLImageTargetRenderbufferStorageOES", 812 (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES }, 813 { "glClipPlanef", 814 (__eglMustCastToProperFunctionPointerType)&glClipPlanef }, 815 { "glClipPlanex", 816 (__eglMustCastToProperFunctionPointerType)&glClipPlanex }, 817 { "glBindBuffer", 818 (__eglMustCastToProperFunctionPointerType)&glBindBuffer }, 819 { "glBufferData", 820 (__eglMustCastToProperFunctionPointerType)&glBufferData }, 821 { "glBufferSubData", 822 (__eglMustCastToProperFunctionPointerType)&glBufferSubData }, 823 { "glDeleteBuffers", 824 (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers }, 825 { "glGenBuffers", 826 (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, 827}; 828 829/* 830 * In the lists below, attributes names MUST be sorted. 831 * Additionally, all configs must be sorted according to 832 * the EGL specification. 833 */ 834 835static config_pair_t const config_base_attribute_list[] = { 836 { EGL_STENCIL_SIZE, 0 }, 837 { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG }, 838 { EGL_LEVEL, 0 }, 839 { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS }, 840 { EGL_MAX_PBUFFER_PIXELS, 841 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS }, 842 { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS }, 843 { EGL_NATIVE_RENDERABLE, EGL_TRUE }, 844 { EGL_NATIVE_VISUAL_ID, 0 }, 845 { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGB_565 }, 846 { EGL_SAMPLES, 0 }, 847 { EGL_SAMPLE_BUFFERS, 0 }, 848 { EGL_TRANSPARENT_TYPE, EGL_NONE }, 849 { EGL_TRANSPARENT_BLUE_VALUE, 0 }, 850 { EGL_TRANSPARENT_GREEN_VALUE, 0 }, 851 { EGL_TRANSPARENT_RED_VALUE, 0 }, 852 { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE }, 853 { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE }, 854 { EGL_MIN_SWAP_INTERVAL, 1 }, 855 { EGL_MAX_SWAP_INTERVAL, 4 }, 856}; 857 858// These configs can override the base attribute list 859// NOTE: when adding a config here, don't forget to update eglCreate*Surface() 860 861static config_pair_t const config_0_attribute_list[] = { 862 { EGL_BUFFER_SIZE, 16 }, 863 { EGL_ALPHA_SIZE, 0 }, 864 { EGL_BLUE_SIZE, 5 }, 865 { EGL_GREEN_SIZE, 6 }, 866 { EGL_RED_SIZE, 5 }, 867 { EGL_DEPTH_SIZE, 0 }, 868 { EGL_CONFIG_ID, 0 }, 869 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 870}; 871 872static config_pair_t const config_1_attribute_list[] = { 873 { EGL_BUFFER_SIZE, 16 }, 874 { EGL_ALPHA_SIZE, 0 }, 875 { EGL_BLUE_SIZE, 5 }, 876 { EGL_GREEN_SIZE, 6 }, 877 { EGL_RED_SIZE, 5 }, 878 { EGL_DEPTH_SIZE, 16 }, 879 { EGL_CONFIG_ID, 1 }, 880 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 881}; 882 883static config_pair_t const config_2_attribute_list[] = { 884 { EGL_BUFFER_SIZE, 32 }, 885 { EGL_ALPHA_SIZE, 8 }, 886 { EGL_BLUE_SIZE, 8 }, 887 { EGL_GREEN_SIZE, 8 }, 888 { EGL_RED_SIZE, 8 }, 889 { EGL_DEPTH_SIZE, 0 }, 890 { EGL_CONFIG_ID, 2 }, 891 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 892}; 893 894static config_pair_t const config_3_attribute_list[] = { 895 { EGL_BUFFER_SIZE, 32 }, 896 { EGL_ALPHA_SIZE, 8 }, 897 { EGL_BLUE_SIZE, 8 }, 898 { EGL_GREEN_SIZE, 8 }, 899 { EGL_RED_SIZE, 8 }, 900 { EGL_DEPTH_SIZE, 16 }, 901 { EGL_CONFIG_ID, 3 }, 902 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 903}; 904 905static config_pair_t const config_4_attribute_list[] = { 906 { EGL_BUFFER_SIZE, 8 }, 907 { EGL_ALPHA_SIZE, 8 }, 908 { EGL_BLUE_SIZE, 0 }, 909 { EGL_GREEN_SIZE, 0 }, 910 { EGL_RED_SIZE, 0 }, 911 { EGL_DEPTH_SIZE, 0 }, 912 { EGL_CONFIG_ID, 4 }, 913 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 914}; 915 916static config_pair_t const config_5_attribute_list[] = { 917 { EGL_BUFFER_SIZE, 8 }, 918 { EGL_ALPHA_SIZE, 8 }, 919 { EGL_BLUE_SIZE, 0 }, 920 { EGL_GREEN_SIZE, 0 }, 921 { EGL_RED_SIZE, 0 }, 922 { EGL_DEPTH_SIZE, 16 }, 923 { EGL_CONFIG_ID, 5 }, 924 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, 925}; 926 927static configs_t const gConfigs[] = { 928 { config_0_attribute_list, NELEM(config_0_attribute_list) }, 929 { config_1_attribute_list, NELEM(config_1_attribute_list) }, 930 { config_2_attribute_list, NELEM(config_2_attribute_list) }, 931 { config_3_attribute_list, NELEM(config_3_attribute_list) }, 932 { config_4_attribute_list, NELEM(config_4_attribute_list) }, 933 { config_5_attribute_list, NELEM(config_5_attribute_list) }, 934}; 935 936static config_management_t const gConfigManagement[] = { 937 { EGL_BUFFER_SIZE, config_management_t::atLeast }, 938 { EGL_ALPHA_SIZE, config_management_t::atLeast }, 939 { EGL_BLUE_SIZE, config_management_t::atLeast }, 940 { EGL_GREEN_SIZE, config_management_t::atLeast }, 941 { EGL_RED_SIZE, config_management_t::atLeast }, 942 { EGL_DEPTH_SIZE, config_management_t::atLeast }, 943 { EGL_STENCIL_SIZE, config_management_t::atLeast }, 944 { EGL_CONFIG_CAVEAT, config_management_t::exact }, 945 { EGL_CONFIG_ID, config_management_t::exact }, 946 { EGL_LEVEL, config_management_t::exact }, 947 { EGL_MAX_PBUFFER_HEIGHT, config_management_t::exact }, 948 { EGL_MAX_PBUFFER_PIXELS, config_management_t::exact }, 949 { EGL_MAX_PBUFFER_WIDTH, config_management_t::exact }, 950 { EGL_NATIVE_RENDERABLE, config_management_t::exact }, 951 { EGL_NATIVE_VISUAL_ID, config_management_t::exact }, 952 { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact }, 953 { EGL_SAMPLES, config_management_t::exact }, 954 { EGL_SAMPLE_BUFFERS, config_management_t::exact }, 955 { EGL_SURFACE_TYPE, config_management_t::mask }, 956 { EGL_TRANSPARENT_TYPE, config_management_t::exact }, 957 { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact }, 958 { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact }, 959 { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact }, 960 { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact }, 961 { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact }, 962 { EGL_MIN_SWAP_INTERVAL, config_management_t::exact }, 963 { EGL_MAX_SWAP_INTERVAL, config_management_t::exact }, 964}; 965 966static config_pair_t const config_defaults[] = { 967 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT }, 968}; 969 970// ---------------------------------------------------------------------------- 971 972template<typename T> 973static int binarySearch(T const sortedArray[], int first, int last, EGLint key) 974{ 975 while (first <= last) { 976 int mid = (first + last) / 2; 977 if (key > sortedArray[mid].key) { 978 first = mid + 1; 979 } else if (key < sortedArray[mid].key) { 980 last = mid - 1; 981 } else { 982 return mid; 983 } 984 } 985 return -1; 986} 987 988static int isAttributeMatching(int i, EGLint attr, EGLint val) 989{ 990 // look for the attribute in all of our configs 991 config_pair_t const* configFound = gConfigs[i].array; 992 int index = binarySearch<config_pair_t>( 993 gConfigs[i].array, 994 0, gConfigs[i].size-1, 995 attr); 996 if (index < 0) { 997 configFound = config_base_attribute_list; 998 index = binarySearch<config_pair_t>( 999 config_base_attribute_list, 1000 0, NELEM(config_base_attribute_list)-1, 1001 attr); 1002 } 1003 if (index >= 0) { 1004 // attribute found, check if this config could match 1005 int cfgMgtIndex = binarySearch<config_management_t>( 1006 gConfigManagement, 1007 0, NELEM(gConfigManagement)-1, 1008 attr); 1009 if (index >= 0) { 1010 bool match = gConfigManagement[cfgMgtIndex].match( 1011 val, configFound[index].value); 1012 if (match) { 1013 // this config matches 1014 return 1; 1015 } 1016 } else { 1017 // attribute not found. this should NEVER happen. 1018 } 1019 } else { 1020 // error, this attribute doesn't exist 1021 } 1022 return 0; 1023} 1024 1025static int makeCurrent(ogles_context_t* gl) 1026{ 1027 ogles_context_t* current = (ogles_context_t*)getGlThreadSpecific(); 1028 if (gl) { 1029 egl_context_t* c = egl_context_t::context(gl); 1030 if (c->flags & egl_context_t::IS_CURRENT) { 1031 if (current != gl) { 1032 // it is an error to set a context current, if it's already 1033 // current to another thread 1034 return -1; 1035 } 1036 } else { 1037 if (current) { 1038 // mark the current context as not current, and flush 1039 glFlush(); 1040 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; 1041 } 1042 } 1043 if (!(c->flags & egl_context_t::IS_CURRENT)) { 1044 // The context is not current, make it current! 1045 setGlThreadSpecific(gl); 1046 c->flags |= egl_context_t::IS_CURRENT; 1047 } 1048 } else { 1049 if (current) { 1050 // mark the current context as not current, and flush 1051 glFlush(); 1052 egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; 1053 } 1054 // this thread has no context attached to it 1055 setGlThreadSpecific(0); 1056 } 1057 return 0; 1058} 1059 1060static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config, 1061 EGLint attribute, EGLint *value) 1062{ 1063 size_t numConfigs = NELEM(gConfigs); 1064 int index = (int)config; 1065 if (uint32_t(index) >= numConfigs) 1066 return setError(EGL_BAD_CONFIG, EGL_FALSE); 1067 1068 int attrIndex; 1069 attrIndex = binarySearch<config_pair_t>( 1070 gConfigs[index].array, 1071 0, gConfigs[index].size-1, 1072 attribute); 1073 if (attrIndex>=0) { 1074 *value = gConfigs[index].array[attrIndex].value; 1075 return EGL_TRUE; 1076 } 1077 1078 attrIndex = binarySearch<config_pair_t>( 1079 config_base_attribute_list, 1080 0, NELEM(config_base_attribute_list)-1, 1081 attribute); 1082 if (attrIndex>=0) { 1083 *value = config_base_attribute_list[attrIndex].value; 1084 return EGL_TRUE; 1085 } 1086 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); 1087} 1088 1089static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, 1090 NativeWindowType window, const EGLint *attrib_list) 1091{ 1092 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1093 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1094 if (window == 0) 1095 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1096 1097 EGLint surfaceType; 1098 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) 1099 return EGL_FALSE; 1100 1101 if (!(surfaceType & EGL_WINDOW_BIT)) 1102 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1103 1104 EGLint configID; 1105 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) 1106 return EGL_FALSE; 1107 1108 int32_t depthFormat; 1109 int32_t pixelFormat; 1110 switch(configID) { 1111 case 0: 1112 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1113 depthFormat = 0; 1114 break; 1115 case 1: 1116 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1117 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1118 break; 1119 case 2: 1120 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1121 depthFormat = 0; 1122 break; 1123 case 3: 1124 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1125 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1126 break; 1127 case 4: 1128 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1129 depthFormat = 0; 1130 break; 1131 case 5: 1132 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1133 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1134 break; 1135 default: 1136 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1137 } 1138 1139 // FIXME: we don't have access to the pixelFormat here just yet. 1140 // (it's possible that the surface is not fully initialized) 1141 // maybe this should be done after the page-flip 1142 //if (EGLint(info.format) != pixelFormat) 1143 // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1144 1145 egl_surface_t* surface; 1146 surface = new egl_window_surface_v2_t(dpy, config, depthFormat, 1147 static_cast<android_native_window_t*>(window)); 1148 1149 if (!surface->isValid()) { 1150 // there was a problem in the ctor, the error 1151 // flag has been set. 1152 delete surface; 1153 surface = 0; 1154 } 1155 return surface; 1156} 1157 1158static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config, 1159 NativePixmapType pixmap, const EGLint *attrib_list) 1160{ 1161 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1162 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1163 if (pixmap == 0) 1164 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1165 1166 EGLint surfaceType; 1167 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) 1168 return EGL_FALSE; 1169 1170 if (!(surfaceType & EGL_PIXMAP_BIT)) 1171 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1172 1173 EGLint configID; 1174 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) 1175 return EGL_FALSE; 1176 1177 int32_t depthFormat; 1178 int32_t pixelFormat; 1179 switch(configID) { 1180 case 0: 1181 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1182 depthFormat = 0; 1183 break; 1184 case 1: 1185 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1186 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1187 break; 1188 case 2: 1189 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1190 depthFormat = 0; 1191 break; 1192 case 3: 1193 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1194 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1195 break; 1196 case 4: 1197 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1198 depthFormat = 0; 1199 break; 1200 case 5: 1201 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1202 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1203 break; 1204 default: 1205 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1206 } 1207 1208 if (pixmap->format != pixelFormat) 1209 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1210 1211 egl_surface_t* surface = 1212 new egl_pixmap_surface_t(dpy, config, depthFormat, 1213 static_cast<egl_native_pixmap_t*>(pixmap)); 1214 1215 if (!surface->isValid()) { 1216 // there was a problem in the ctor, the error 1217 // flag has been set. 1218 delete surface; 1219 surface = 0; 1220 } 1221 return surface; 1222} 1223 1224static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, 1225 const EGLint *attrib_list) 1226{ 1227 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1228 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1229 1230 EGLint surfaceType; 1231 if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) 1232 return EGL_FALSE; 1233 1234 if (!(surfaceType & EGL_PBUFFER_BIT)) 1235 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1236 1237 EGLint configID; 1238 if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) 1239 return EGL_FALSE; 1240 1241 int32_t depthFormat; 1242 int32_t pixelFormat; 1243 switch(configID) { 1244 case 0: 1245 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1246 depthFormat = 0; 1247 break; 1248 case 1: 1249 pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 1250 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1251 break; 1252 case 2: 1253 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1254 depthFormat = 0; 1255 break; 1256 case 3: 1257 pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 1258 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1259 break; 1260 case 4: 1261 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1262 depthFormat = 0; 1263 break; 1264 case 5: 1265 pixelFormat = GGL_PIXEL_FORMAT_A_8; 1266 depthFormat = GGL_PIXEL_FORMAT_Z_16; 1267 break; 1268 default: 1269 return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); 1270 } 1271 1272 int32_t w = 0; 1273 int32_t h = 0; 1274 while (attrib_list[0]) { 1275 if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1]; 1276 if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1]; 1277 attrib_list+=2; 1278 } 1279 1280 egl_surface_t* surface = 1281 new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat); 1282 1283 if (!surface->isValid()) { 1284 // there was a problem in the ctor, the error 1285 // flag has been set. 1286 delete surface; 1287 surface = 0; 1288 } 1289 return surface; 1290} 1291 1292// ---------------------------------------------------------------------------- 1293}; // namespace android 1294// ---------------------------------------------------------------------------- 1295 1296using namespace android; 1297 1298// ---------------------------------------------------------------------------- 1299// Initialization 1300// ---------------------------------------------------------------------------- 1301 1302EGLDisplay eglGetDisplay(NativeDisplayType display) 1303{ 1304#ifndef HAVE_ANDROID_OS 1305 // this just needs to be done once 1306 if (gGLKey == -1) { 1307 pthread_mutex_lock(&gInitMutex); 1308 if (gGLKey == -1) 1309 pthread_key_create(&gGLKey, NULL); 1310 pthread_mutex_unlock(&gInitMutex); 1311 } 1312#endif 1313 if (display == EGL_DEFAULT_DISPLAY) { 1314 EGLDisplay dpy = (EGLDisplay)1; 1315 egl_display_t& d = egl_display_t::get_display(dpy); 1316 d.type = display; 1317 return dpy; 1318 } 1319 return EGL_NO_DISPLAY; 1320} 1321 1322EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 1323{ 1324 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1325 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1326 1327 EGLBoolean res = EGL_TRUE; 1328 egl_display_t& d = egl_display_t::get_display(dpy); 1329 1330 if (android_atomic_inc(&d.initialized) == 0) { 1331 // initialize stuff here if needed 1332 //pthread_mutex_lock(&gInitMutex); 1333 //pthread_mutex_unlock(&gInitMutex); 1334 } 1335 1336 if (res == EGL_TRUE) { 1337 if (major != NULL) *major = VERSION_MAJOR; 1338 if (minor != NULL) *minor = VERSION_MINOR; 1339 } 1340 return res; 1341} 1342 1343EGLBoolean eglTerminate(EGLDisplay dpy) 1344{ 1345 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1346 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1347 1348 EGLBoolean res = EGL_TRUE; 1349 egl_display_t& d = egl_display_t::get_display(dpy); 1350 if (android_atomic_dec(&d.initialized) == 1) { 1351 // TODO: destroy all resources (surfaces, contexts, etc...) 1352 //pthread_mutex_lock(&gInitMutex); 1353 //pthread_mutex_unlock(&gInitMutex); 1354 } 1355 return res; 1356} 1357 1358// ---------------------------------------------------------------------------- 1359// configuration 1360// ---------------------------------------------------------------------------- 1361 1362EGLBoolean eglGetConfigs( EGLDisplay dpy, 1363 EGLConfig *configs, 1364 EGLint config_size, EGLint *num_config) 1365{ 1366 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1367 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1368 1369 GLint numConfigs = NELEM(gConfigs); 1370 if (!configs) { 1371 *num_config = numConfigs; 1372 return EGL_TRUE; 1373 } 1374 GLint i; 1375 for (i=0 ; i<numConfigs && i<config_size ; i++) { 1376 *configs++ = (EGLConfig)i; 1377 } 1378 *num_config = i; 1379 return EGL_TRUE; 1380} 1381 1382EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 1383 EGLConfig *configs, EGLint config_size, 1384 EGLint *num_config) 1385{ 1386 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1387 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1388 1389 if (ggl_unlikely(num_config==0)) { 1390 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1391 } 1392 1393 if (ggl_unlikely(attrib_list==0)) { 1394 *num_config = 0; 1395 return EGL_TRUE; 1396 } 1397 1398 int numAttributes = 0; 1399 int numConfigs = NELEM(gConfigs); 1400 uint32_t possibleMatch = (1<<numConfigs)-1; 1401 while(possibleMatch && *attrib_list != EGL_NONE) { 1402 numAttributes++; 1403 EGLint attr = *attrib_list++; 1404 EGLint val = *attrib_list++; 1405 for (int i=0 ; i<numConfigs ; i++) { 1406 if (!(possibleMatch & (1<<i))) 1407 continue; 1408 if (isAttributeMatching(i, attr, val) == 0) { 1409 possibleMatch &= ~(1<<i); 1410 } 1411 } 1412 } 1413 1414 // now, handle the attributes which have a useful default value 1415 for (size_t j=0 ; j<NELEM(config_defaults) ; j++) { 1416 // see if this attribute was specified, if not apply its 1417 // default value 1418 if (binarySearch<config_pair_t>( 1419 (config_pair_t const*)attrib_list, 1420 0, numAttributes, 1421 config_defaults[j].key) < 0) 1422 { 1423 for (int i=0 ; i<numConfigs ; i++) { 1424 if (!(possibleMatch & (1<<i))) 1425 continue; 1426 if (isAttributeMatching(i, 1427 config_defaults[j].key, 1428 config_defaults[j].value) == 0) 1429 { 1430 possibleMatch &= ~(1<<i); 1431 } 1432 } 1433 } 1434 } 1435 1436 // return the configurations found 1437 int n=0; 1438 if (possibleMatch) { 1439 if (configs) { 1440 for (int i=0 ; config_size && i<numConfigs ; i++) { 1441 if (possibleMatch & (1<<i)) { 1442 *configs++ = (EGLConfig)i; 1443 config_size--; 1444 n++; 1445 } 1446 } 1447 } else { 1448 for (int i=0 ; i<numConfigs ; i++) { 1449 if (possibleMatch & (1<<i)) { 1450 n++; 1451 } 1452 } 1453 } 1454 } 1455 *num_config = n; 1456 return EGL_TRUE; 1457} 1458 1459EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 1460 EGLint attribute, EGLint *value) 1461{ 1462 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1463 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1464 1465 return getConfigAttrib(dpy, config, attribute, value); 1466} 1467 1468// ---------------------------------------------------------------------------- 1469// surfaces 1470// ---------------------------------------------------------------------------- 1471 1472EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 1473 NativeWindowType window, 1474 const EGLint *attrib_list) 1475{ 1476 return createWindowSurface(dpy, config, window, attrib_list); 1477} 1478 1479EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 1480 NativePixmapType pixmap, 1481 const EGLint *attrib_list) 1482{ 1483 return createPixmapSurface(dpy, config, pixmap, attrib_list); 1484} 1485 1486EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 1487 const EGLint *attrib_list) 1488{ 1489 return createPbufferSurface(dpy, config, attrib_list); 1490} 1491 1492EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) 1493{ 1494 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1495 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1496 if (eglSurface != EGL_NO_SURFACE) { 1497 egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) ); 1498 if (surface->magic != egl_surface_t::MAGIC) 1499 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1500 if (surface->dpy != dpy) 1501 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1502 if (surface->ctx) { 1503 // FIXME: this surface is current check what the spec says 1504 surface->disconnect(); 1505 surface->ctx = 0; 1506 } 1507 delete surface; 1508 } 1509 return EGL_TRUE; 1510} 1511 1512EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface, 1513 EGLint attribute, EGLint *value) 1514{ 1515 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1516 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1517 egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface); 1518 if (surface->dpy != dpy) 1519 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1520 1521 EGLBoolean ret = EGL_TRUE; 1522 switch (attribute) { 1523 case EGL_CONFIG_ID: 1524 ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value); 1525 break; 1526 case EGL_WIDTH: 1527 *value = surface->getWidth(); 1528 break; 1529 case EGL_HEIGHT: 1530 *value = surface->getHeight(); 1531 break; 1532 case EGL_LARGEST_PBUFFER: 1533 // not modified for a window or pixmap surface 1534 break; 1535 case EGL_TEXTURE_FORMAT: 1536 *value = EGL_NO_TEXTURE; 1537 break; 1538 case EGL_TEXTURE_TARGET: 1539 *value = EGL_NO_TEXTURE; 1540 break; 1541 case EGL_MIPMAP_TEXTURE: 1542 *value = EGL_FALSE; 1543 break; 1544 case EGL_MIPMAP_LEVEL: 1545 *value = 0; 1546 break; 1547 case EGL_RENDER_BUFFER: 1548 // TODO: return the real RENDER_BUFFER here 1549 *value = EGL_BACK_BUFFER; 1550 break; 1551 case EGL_HORIZONTAL_RESOLUTION: 1552 // pixel/mm * EGL_DISPLAY_SCALING 1553 *value = surface->getHorizontalResolution(); 1554 break; 1555 case EGL_VERTICAL_RESOLUTION: 1556 // pixel/mm * EGL_DISPLAY_SCALING 1557 *value = surface->getVerticalResolution(); 1558 break; 1559 case EGL_PIXEL_ASPECT_RATIO: { 1560 // w/h * EGL_DISPLAY_SCALING 1561 int wr = surface->getHorizontalResolution(); 1562 int hr = surface->getVerticalResolution(); 1563 *value = (wr * EGL_DISPLAY_SCALING) / hr; 1564 } break; 1565 case EGL_SWAP_BEHAVIOR: 1566 *value = surface->getSwapBehavior(); 1567 break; 1568 default: 1569 ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); 1570 } 1571 return ret; 1572} 1573 1574EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 1575 EGLContext share_list, const EGLint *attrib_list) 1576{ 1577 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1578 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1579 1580 ogles_context_t* gl = ogles_init(sizeof(egl_context_t)); 1581 if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); 1582 1583 egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base); 1584 c->flags = egl_context_t::NEVER_CURRENT; 1585 c->dpy = dpy; 1586 c->config = config; 1587 c->read = 0; 1588 c->draw = 0; 1589 return (EGLContext)gl; 1590} 1591 1592EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 1593{ 1594 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1595 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1596 egl_context_t* c = egl_context_t::context(ctx); 1597 if (c->flags & egl_context_t::IS_CURRENT) 1598 setGlThreadSpecific(0); 1599 ogles_uninit((ogles_context_t*)ctx); 1600 return EGL_TRUE; 1601} 1602 1603EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 1604 EGLSurface read, EGLContext ctx) 1605{ 1606 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1607 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1608 if (draw) { 1609 egl_surface_t* s = (egl_surface_t*)draw; 1610 if (s->dpy != dpy) 1611 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1612 // TODO: check that draw and read are compatible with the context 1613 } 1614 1615 EGLContext current_ctx = EGL_NO_CONTEXT; 1616 1617 if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) 1618 return setError(EGL_BAD_MATCH, EGL_FALSE); 1619 1620 if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT)) 1621 return setError(EGL_BAD_MATCH, EGL_FALSE); 1622 1623 if (ctx == EGL_NO_CONTEXT) { 1624 // if we're detaching, we need the current context 1625 current_ctx = (EGLContext)getGlThreadSpecific(); 1626 } else { 1627 egl_context_t* c = egl_context_t::context(ctx); 1628 egl_surface_t* d = (egl_surface_t*)draw; 1629 egl_surface_t* r = (egl_surface_t*)read; 1630 if ((d && d->ctx && d->ctx != ctx) || 1631 (r && r->ctx && r->ctx != ctx)) { 1632 // one of the surface is bound to a context in another thread 1633 return setError(EGL_BAD_ACCESS, EGL_FALSE); 1634 } 1635 } 1636 1637 ogles_context_t* gl = (ogles_context_t*)ctx; 1638 if (makeCurrent(gl) == 0) { 1639 if (ctx) { 1640 egl_context_t* c = egl_context_t::context(ctx); 1641 egl_surface_t* d = (egl_surface_t*)draw; 1642 egl_surface_t* r = (egl_surface_t*)read; 1643 1644 if (c->draw) { 1645 reinterpret_cast<egl_surface_t*>(c->draw)->disconnect(); 1646 } 1647 if (c->read) { 1648 // FIXME: unlock/disconnect the read surface too 1649 } 1650 1651 c->draw = draw; 1652 c->read = read; 1653 1654 if (c->flags & egl_context_t::NEVER_CURRENT) { 1655 c->flags &= ~egl_context_t::NEVER_CURRENT; 1656 GLint w = 0; 1657 GLint h = 0; 1658 if (draw) { 1659 w = d->getWidth(); 1660 h = d->getHeight(); 1661 } 1662 ogles_surfaceport(gl, 0, 0); 1663 ogles_viewport(gl, 0, 0, w, h); 1664 ogles_scissor(gl, 0, 0, w, h); 1665 } 1666 if (d) { 1667 d->connect(); 1668 d->ctx = ctx; 1669 d->bindDrawSurface(gl); 1670 } 1671 if (r) { 1672 // FIXME: lock/connect the read surface too 1673 r->ctx = ctx; 1674 r->bindReadSurface(gl); 1675 } 1676 } else { 1677 // if surfaces were bound to the context bound to this thread 1678 // mark then as unbound. 1679 if (current_ctx) { 1680 egl_context_t* c = egl_context_t::context(current_ctx); 1681 egl_surface_t* d = (egl_surface_t*)c->draw; 1682 egl_surface_t* r = (egl_surface_t*)c->read; 1683 if (d) { 1684 c->draw = 0; 1685 d->ctx = EGL_NO_CONTEXT; 1686 d->disconnect(); 1687 } 1688 if (r) { 1689 c->read = 0; 1690 r->ctx = EGL_NO_CONTEXT; 1691 // FIXME: unlock/disconnect the read surface too 1692 } 1693 } 1694 } 1695 return EGL_TRUE; 1696 } 1697 return setError(EGL_BAD_ACCESS, EGL_FALSE); 1698} 1699 1700EGLContext eglGetCurrentContext(void) 1701{ 1702 // eglGetCurrentContext returns the current EGL rendering context, 1703 // as specified by eglMakeCurrent. If no context is current, 1704 // EGL_NO_CONTEXT is returned. 1705 return (EGLContext)getGlThreadSpecific(); 1706} 1707 1708EGLSurface eglGetCurrentSurface(EGLint readdraw) 1709{ 1710 // eglGetCurrentSurface returns the read or draw surface attached 1711 // to the current EGL rendering context, as specified by eglMakeCurrent. 1712 // If no context is current, EGL_NO_SURFACE is returned. 1713 EGLContext ctx = (EGLContext)getGlThreadSpecific(); 1714 if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE; 1715 egl_context_t* c = egl_context_t::context(ctx); 1716 if (readdraw == EGL_READ) { 1717 return c->read; 1718 } else if (readdraw == EGL_DRAW) { 1719 return c->draw; 1720 } 1721 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1722} 1723 1724EGLDisplay eglGetCurrentDisplay(void) 1725{ 1726 // eglGetCurrentDisplay returns the current EGL display connection 1727 // for the current EGL rendering context, as specified by eglMakeCurrent. 1728 // If no context is current, EGL_NO_DISPLAY is returned. 1729 EGLContext ctx = (EGLContext)getGlThreadSpecific(); 1730 if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY; 1731 egl_context_t* c = egl_context_t::context(ctx); 1732 return c->dpy; 1733} 1734 1735EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 1736 EGLint attribute, EGLint *value) 1737{ 1738 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1739 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1740 egl_context_t* c = egl_context_t::context(ctx); 1741 switch (attribute) { 1742 case EGL_CONFIG_ID: 1743 // Returns the ID of the EGL frame buffer configuration with 1744 // respect to which the context was created 1745 return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value); 1746 } 1747 return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); 1748} 1749 1750EGLBoolean eglWaitGL(void) 1751{ 1752 return EGL_TRUE; 1753} 1754 1755EGLBoolean eglWaitNative(EGLint engine) 1756{ 1757 return EGL_TRUE; 1758} 1759 1760EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1761{ 1762 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1763 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1764 1765 egl_surface_t* d = static_cast<egl_surface_t*>(draw); 1766 if (d->dpy != dpy) 1767 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1768 1769 // post the surface 1770 d->swapBuffers(); 1771 1772 // if it's bound to a context, update the buffer 1773 if (d->ctx != EGL_NO_CONTEXT) { 1774 d->bindDrawSurface((ogles_context_t*)d->ctx); 1775 // if this surface is also the read surface of the context 1776 // it is bound to, make sure to update the read buffer as well. 1777 // The EGL spec is a little unclear about this. 1778 egl_context_t* c = egl_context_t::context(d->ctx); 1779 if (c->read == draw) { 1780 d->bindReadSurface((ogles_context_t*)d->ctx); 1781 } 1782 } 1783 1784 return EGL_TRUE; 1785} 1786 1787EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1788 NativePixmapType target) 1789{ 1790 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1791 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1792 // TODO: eglCopyBuffers() 1793 return EGL_FALSE; 1794} 1795 1796EGLint eglGetError(void) 1797{ 1798 return getError(); 1799} 1800 1801const char* eglQueryString(EGLDisplay dpy, EGLint name) 1802{ 1803 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1804 return setError(EGL_BAD_DISPLAY, (const char*)0); 1805 1806 switch (name) { 1807 case EGL_VENDOR: 1808 return gVendorString; 1809 case EGL_VERSION: 1810 return gVersionString; 1811 case EGL_EXTENSIONS: 1812 return gExtensionsString; 1813 case EGL_CLIENT_APIS: 1814 return gClientApiString; 1815 } 1816 return setError(EGL_BAD_PARAMETER, (const char *)0); 1817} 1818 1819// ---------------------------------------------------------------------------- 1820// EGL 1.1 1821// ---------------------------------------------------------------------------- 1822 1823EGLBoolean eglSurfaceAttrib( 1824 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1825{ 1826 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1827 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1828 // TODO: eglSurfaceAttrib() 1829 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1830} 1831 1832EGLBoolean eglBindTexImage( 1833 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1834{ 1835 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1836 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1837 // TODO: eglBindTexImage() 1838 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1839} 1840 1841EGLBoolean eglReleaseTexImage( 1842 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1843{ 1844 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1845 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1846 // TODO: eglReleaseTexImage() 1847 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1848} 1849 1850EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1851{ 1852 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1853 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1854 // TODO: eglSwapInterval() 1855 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1856} 1857 1858// ---------------------------------------------------------------------------- 1859// EGL 1.2 1860// ---------------------------------------------------------------------------- 1861 1862EGLBoolean eglBindAPI(EGLenum api) 1863{ 1864 if (api != EGL_OPENGL_ES_API) 1865 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1866 return EGL_TRUE; 1867} 1868 1869EGLenum eglQueryAPI(void) 1870{ 1871 return EGL_OPENGL_ES_API; 1872} 1873 1874EGLBoolean eglWaitClient(void) 1875{ 1876 glFinish(); 1877 return EGL_TRUE; 1878} 1879 1880EGLBoolean eglReleaseThread(void) 1881{ 1882 // TODO: eglReleaseThread() 1883 return EGL_TRUE; 1884} 1885 1886EGLSurface eglCreatePbufferFromClientBuffer( 1887 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1888 EGLConfig config, const EGLint *attrib_list) 1889{ 1890 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1891 return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); 1892 // TODO: eglCreatePbufferFromClientBuffer() 1893 return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1894} 1895 1896// ---------------------------------------------------------------------------- 1897// EGL_EGLEXT_VERSION 3 1898// ---------------------------------------------------------------------------- 1899 1900void (*eglGetProcAddress (const char *procname))() 1901{ 1902 extention_map_t const * const map = gExtentionMap; 1903 for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) { 1904 if (!strcmp(procname, map[i].name)) { 1905 return map[i].address; 1906 } 1907 } 1908 return NULL; 1909} 1910 1911EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1912 const EGLint *attrib_list) 1913{ 1914 EGLBoolean result = EGL_FALSE; 1915 return result; 1916} 1917 1918EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1919{ 1920 EGLBoolean result = EGL_FALSE; 1921 return result; 1922} 1923 1924EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1925 EGLClientBuffer buffer, const EGLint *attrib_list) 1926{ 1927 if (egl_display_t::is_valid(dpy) == EGL_FALSE) { 1928 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); 1929 } 1930 if (ctx != EGL_NO_CONTEXT) { 1931 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1932 } 1933 if (target != EGL_NATIVE_BUFFER_ANDROID) { 1934 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1935 } 1936 1937 android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer; 1938 1939 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) 1940 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1941 1942 if (native_buffer->common.version != sizeof(android_native_buffer_t)) 1943 return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1944 1945 native_buffer->common.incRef(&native_buffer->common); 1946 return (EGLImageKHR)native_buffer; 1947} 1948 1949EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1950{ 1951 if (egl_display_t::is_valid(dpy) == EGL_FALSE) { 1952 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1953 } 1954 1955 android_native_buffer_t* native_buffer = (android_native_buffer_t*)img; 1956 1957 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) 1958 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1959 1960 if (native_buffer->common.version != sizeof(android_native_buffer_t)) 1961 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1962 1963 native_buffer->common.decRef(&native_buffer->common); 1964 1965 return EGL_TRUE; 1966} 1967 1968// ---------------------------------------------------------------------------- 1969// ANDROID extensions 1970// ---------------------------------------------------------------------------- 1971 1972EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 1973 EGLint left, EGLint top, EGLint width, EGLint height) 1974{ 1975 if (egl_display_t::is_valid(dpy) == EGL_FALSE) 1976 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1977 1978 egl_surface_t* d = static_cast<egl_surface_t*>(draw); 1979 if (d->dpy != dpy) 1980 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1981 1982 // post the surface 1983 d->setSwapRectangle(left, top, width, height); 1984 1985 return EGL_TRUE; 1986} 1987