Import EGL/GLES translator

This commit is contained in:
Simon Fels 2016-08-23 23:41:53 +02:00
commit 085e3c56a3
91 changed files with 17910 additions and 8 deletions

View file

@ -7,7 +7,6 @@ include_directories(
${CMAKE_SOURCE_DIR}/external/android-emugl/host/include
${CMAKE_SOURCE_DIR}/external/android-emugl/shared/OpenglCodecCommon
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/Translator/include
${CMAKE_SOURCE_DIR}/external/android-emugl/host/include/libOpenglRender
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/GLESv1_dec
${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/GLESv1_dec
@ -15,6 +14,7 @@ include_directories(
${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/GLESv2_dec
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/renderControl_dec
${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/renderControl_dec
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/Translator/
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/Translator/include
${MIRCLIENT_INCLUDE_DIRS})

View file

@ -3,3 +3,4 @@ add_subdirectory(GLESv2_dec)
add_subdirectory(libOpenGLESDispatch)
add_subdirectory(libOpenglRender)
add_subdirectory(renderControl_dec)
add_subdirectory(Translator)

View file

@ -0,0 +1,4 @@
add_subdirectory(GLcommon)
add_subdirectory(EGL)
add_subdirectory(GLES_CM)
add_subdirectory(GLES_V2)

View file

@ -0,0 +1,46 @@
LOCAL_PATH := $(call my-dir)
host_OS_SRCS :=
host_common_LDLIBS :=
ifeq ($(BUILD_TARGET_OS),linux)
host_OS_SRCS = EglOsApi_glx.cpp
host_common_LDLIBS += -lGL -lX11 -ldl -lpthread
endif
ifeq ($(BUILD_TARGET_OS),darwin)
host_OS_SRCS = EglOsApi_darwin.cpp \
MacNative.m \
MacPixelFormatsAttribs.m
host_common_LDLIBS += -Wl,-framework,AppKit
endif
ifeq ($(BUILD_TARGET_OS),windows)
host_OS_SRCS = EglOsApi_wgl.cpp
host_common_LDLIBS += -lgdi32
endif
host_common_SRC_FILES := \
$(host_OS_SRCS) \
ThreadInfo.cpp \
EglImp.cpp \
EglConfig.cpp \
EglContext.cpp \
EglGlobalInfo.cpp \
EglValidate.cpp \
EglSurface.cpp \
EglWindowSurface.cpp \
EglPbufferSurface.cpp \
EglThreadInfo.cpp \
EglDisplay.cpp \
ClientAPIExts.cpp
### EGL host implementation ########################
$(call emugl-begin-host-shared-library,lib$(BUILD_TARGET_SUFFIX)EGL_translator)
$(call emugl-import,libGLcommon)
LOCAL_LDLIBS += $(host_common_LDLIBS)
LOCAL_SRC_FILES := $(host_common_SRC_FILES)
$(call emugl-end-module)

View file

@ -0,0 +1,26 @@
set(SOURCES
ThreadInfo.cpp
EglImp.cpp
EglConfig.cpp
EglContext.cpp
EglGlobalInfo.cpp
EglValidate.cpp
EglSurface.cpp
EglWindowSurface.cpp
EglPbufferSurface.cpp
EglThreadInfo.cpp
EglDisplay.cpp
EglOsApi_glx.cpp
ClientAPIExts.cpp)
include_directories(BEFORE
${EGL_INCLUDE_DIRS}
${GLESv2_INCLUDE_DIRS})
add_library(EGL_translator SHARED ${SOURCES})
target_link_libraries(EGL_translator
GLcommon
${EGL_LDFLAGS}
${EGL_LIBRARIES}
${GLESv2_LDFLAGS}
${GLESv2_LIBRARIES})

View file

@ -0,0 +1,159 @@
/*
* 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 "ClientAPIExts.h"
#include "EglGlobalInfo.h"
#include "GLcommon/GLutils.h"
#include "GLcommon/TranslatorIfaces.h"
#include "ThreadInfo.h"
#include <GLES/gl.h>
#include <GLES/glext.h>
namespace ClientAPIExts
{
//
// define function pointer type for each extention function
// typename has the form __egl_{funcname}_t
//
#define FUNC_TYPE(fname) __egl_ ## fname ## _t
#define API_ENTRY(fname,params,args) \
typedef void (GL_APIENTRY *FUNC_TYPE(fname)) params;
#define API_ENTRY_RET(rtype,fname,params,args) \
typedef rtype (GL_APIENTRY *FUNC_TYPE(fname)) params;
#include "ClientAPIExts.in"
#undef API_ENTRY
#undef API_ENTRY_RET
/////
// Define static table to store the function value for each
// client API. functions pointers will get initialized through
// ClientAPIExts::initClientFuncs function after each client API has been
// loaded.
/////
#define API_ENTRY(fname,params,args) \
FUNC_TYPE(fname) fname;
#define API_ENTRY_RET(rtype,fname,params,args) \
API_ENTRY(fname,params,args)
static struct _ext_table
{
#include "ClientAPIExts.in"
} s_client_extensions[MAX_GLES_VERSION-1];
#undef API_ENTRY
#undef API_ENTRY_RET
//
// This function initialized each entry in the s_client_extensions
// struct at the givven index using the givven client interface
//
void initClientFuncs(const GLESiface *iface, int idx)
{
#define API_ENTRY(fname,params,args) \
s_client_extensions[idx].fname = \
(FUNC_TYPE(fname))iface->getProcAddress(#fname);
#define API_ENTRY_RET(rtype,fname,params,args) \
API_ENTRY(fname,params,args)
//
// reset all func pointers to NULL
//
memset(&s_client_extensions[idx], 0, sizeof(struct _ext_table));
//
// And now query the GLES library for each proc address
//
#include "ClientAPIExts.in"
#undef API_ENTRY
#undef API_ENTRY_RET
}
//
// Define implementation for each extension function which checks
// the current context version and calls to the correct client API
// function.
//
#define API_ENTRY(fname,params,args) \
static void _egl_ ## fname params \
{ \
ThreadInfo* thread = getThreadInfo(); \
if (!thread->eglContext.Ptr()) { \
return; \
} \
int idx = (int)thread->eglContext->version() - 1; \
if (!s_client_extensions[idx].fname) { \
return; \
} \
(*s_client_extensions[idx].fname) args; \
}
#define API_ENTRY_RET(rtype,fname,params,args) \
static rtype _egl_ ## fname params \
{ \
ThreadInfo* thread = getThreadInfo(); \
if (!thread->eglContext.Ptr()) { \
return (rtype)0; \
} \
int idx = (int)thread->eglContext->version() - 1; \
if (!s_client_extensions[idx].fname) { \
return (rtype)0; \
} \
return (*s_client_extensions[idx].fname) args; \
}
#include "ClientAPIExts.in"
#undef API_ENTRY
#undef API_ENTRY_RET
//
// Define a table to map function names to the local _egl_ version of
// the extension function, to be used in eglGetProcAddress.
//
#define API_ENTRY(fname,params,args) \
{ #fname, (__translatorMustCastToProperFunctionPointerType)_egl_ ## fname},
#define API_ENTRY_RET(rtype,fname,params,args) \
API_ENTRY(fname,params,args)
static struct _client_ext_funcs {
const char *fname;
__translatorMustCastToProperFunctionPointerType proc;
} s_client_ext_funcs[] = {
#include "ClientAPIExts.in"
};
static const int numExtFuncs = sizeof(s_client_ext_funcs) /
sizeof(s_client_ext_funcs[0]);
#undef API_ENTRY
#undef API_ENTRY_RET
//
// returns the __egl_ version of the givven extension function name.
//
__translatorMustCastToProperFunctionPointerType getProcAddress(const char *fname)
{
for (int i=0; i<numExtFuncs; i++) {
if (!strcmp(fname, s_client_ext_funcs[i].fname)) {
return s_client_ext_funcs[i].proc;
}
}
return NULL;
}
} // of namespace ClientAPIExts

View file

@ -0,0 +1,29 @@
/*
* 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.
*/
#ifndef _CLIENT_APIS_EXTS_H
#define _CLIENT_APIS_EXTS_H
#include "GLcommon/TranslatorIfaces.h"
namespace ClientAPIExts
{
void initClientFuncs(const GLESiface *iface, int idx);
__translatorMustCastToProperFunctionPointerType getProcAddress(const char *fname);
} // of namespace ClientAPIExts
#endif

View file

@ -0,0 +1,201 @@
//
// Each extension function should have one of the following
// macro definitions:
// API_ENTRY(funcname, paramlist, arglist)
// -or- (in case funciton has return value)
// API_ENTRY_RET(return_type,funcname, paramlist, arglist)
//
API_ENTRY(glEGLImageTargetTexture2DOES,
(GLenum target, GLeglImageOES image),
(target, image))
API_ENTRY(glEGLImageTargetRenderbufferStorageOES,
(GLenum target, GLeglImageOES image),
(target, image))
API_ENTRY(glBlendEquationSeparateOES,
(GLenum modeRGB, GLenum modeAlpha),
(modeRGB, modeAlpha))
API_ENTRY(glBlendFuncSeparateOES,
(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha),
(srcRGB, dstRGB, srcAlpha, dstAlpha))
API_ENTRY(glBlendEquationOES,
(GLenum mode),
(mode))
API_ENTRY(glCurrentPaletteMatrixOES,
(GLuint matrixpaletteindex),
(matrixpaletteindex))
API_ENTRY(glLoadPaletteFromModelViewMatrixOES,
(void),
())
API_ENTRY(glMatrixIndexPointerOES,
(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer),
(size, type, stride, pointer))
API_ENTRY(glWeightPointerOES,
(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer),
(size, type, stride, pointer))
API_ENTRY(glDepthRangefOES,
(GLclampf zNear, GLclampf zFar),
(zNear, zFar))
API_ENTRY(glFrustumfOES,
(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar),
(left, right, bottom, top, zNear, zFar))
API_ENTRY(glOrthofOES,
(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar),
(left, right, bottom, top, zNear, zFar))
API_ENTRY(glClipPlanefOES,
(GLenum plane, const GLfloat *equation),
(plane, equation))
API_ENTRY(glGetClipPlanefOES,
(GLenum pname, GLfloat * eqn),
(pname, eqn))
API_ENTRY(glClearDepthfOES,
(GLclampf depth),
(depth))
API_ENTRY(glPointSizePointerOES,
(GLenum type, GLsizei stride, const GLvoid *pointer),
(type, stride, pointer))
API_ENTRY(glTexGenfOES,
(GLenum coord, GLenum pname, GLfloat param),
(coord, pname, param))
API_ENTRY(glTexGenfvOES,
(GLenum coord, GLenum pname, const GLfloat *params),
(coord, pname, params))
API_ENTRY(glTexGeniOES,
(GLenum coord, GLenum pname, GLint param),
(coord, pname, param))
API_ENTRY(glTexGenivOES,
(GLenum coord, GLenum pname, const GLint *params),
(coord, pname, params))
API_ENTRY(glTexGenxOES,
(GLenum coord, GLenum pname, GLfixed param),
(coord, pname, param))
API_ENTRY(glTexGenxvOES,
(GLenum coord, GLenum pname, const GLfixed *params),
(coord, pname, params))
API_ENTRY(glGetTexGenfvOES,
(GLenum coord, GLenum pname, GLfloat *params),
(coord, pname, params))
API_ENTRY(glGetTexGenivOES,
(GLenum coord, GLenum pname, GLint *params),
(coord, pname, params))
API_ENTRY(glGetTexGenxvOES,
(GLenum coord, GLenum pname, GLfixed *params),
(coord, pname, params))
API_ENTRY_RET(GLboolean,
glIsRenderbufferOES,
(GLuint renderbuffer),
(renderbuffer))
API_ENTRY(glBindRenderbufferOES,
(GLenum target, GLuint renderbuffer),
(target, renderbuffer))
API_ENTRY(glDeleteRenderbuffersOES,
(GLsizei n, const GLuint* renderbuffers),
(n, renderbuffers))
API_ENTRY(glGenRenderbuffersOES,
(GLsizei n, GLuint* renderbuffers),
(n, renderbuffers))
API_ENTRY(glRenderbufferStorageOES,
(GLenum target, GLenum internalformat, GLsizei width, GLsizei height),
(target, internalformat, width, height))
API_ENTRY(glGetRenderbufferParameterivOES,
(GLenum target, GLenum pname, GLint* params),
(target, pname, params))
API_ENTRY_RET(GLboolean,
glIsFramebufferOES,
(GLuint framebuffer),
(framebuffer))
API_ENTRY(glBindFramebufferOES,
(GLenum target, GLuint framebuffer),
(target, framebuffer))
API_ENTRY(glDeleteFramebuffersOES,
(GLsizei n, const GLuint* framebuffers),
(n, framebuffers))
API_ENTRY(glGenFramebuffersOES,
(GLsizei n, GLuint* framebuffers),
(n, framebuffers))
API_ENTRY_RET(GLenum,
glCheckFramebufferStatusOES,
(GLenum target),
(target))
API_ENTRY(glFramebufferTexture2DOES,
(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level),
(target, attachment, textarget, texture, level))
API_ENTRY(glFramebufferRenderbufferOES,
(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer),
(target, attachment, renderbuffertarget, renderbuffer))
API_ENTRY(glGetFramebufferAttachmentParameterivOES,
(GLenum target, GLenum attachment, GLenum pname, GLint* params),
(target, attachment, pname, params))
API_ENTRY(glGenerateMipmapOES,
(GLenum target),
(target))
API_ENTRY(glDrawTexsOES,
(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height),
(x, y, z, width, height))
API_ENTRY(glDrawTexiOES,
(GLint x, GLint y, GLint z, GLint width, GLint height),
(x, y, z, width, height))
API_ENTRY(glDrawTexfOES,
(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height),
(x, y, z, width, height))
API_ENTRY(glDrawTexxOES,
(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height),
(x, y, z, width, height))
API_ENTRY(glDrawTexsvOES,
(const GLshort *coords),
(coords))
API_ENTRY(glDrawTexivOES,
(const GLint *coords),
(coords))
API_ENTRY(glDrawTexfvOES,
(const GLfloat *coords),
(coords))
API_ENTRY(glDrawTexxvOES,
(const GLfixed *coords),
(coords))

View file

@ -0,0 +1,345 @@
/*
* 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 "EglConfig.h"
EglConfig::EglConfig(EGLint red_size,
EGLint green_size,
EGLint blue_size,
EGLint alpha_size,
EGLenum caveat,
EGLint config_id,
EGLint depth_size,
EGLint frame_buffer_level,
EGLint max_pbuffer_width,
EGLint max_pbuffer_height,
EGLint max_pbuffer_size,
EGLBoolean native_renderable,
EGLint renderable_type,
EGLint native_visual_id,
EGLint native_visual_type,
EGLint samples_per_pixel,
EGLint stencil_size,
EGLint surface_type,
EGLenum transparent_type,
EGLint trans_red_val,
EGLint trans_green_val,
EGLint trans_blue_val,
EglOS::PixelFormat* frmt):
m_buffer_size(red_size + green_size + blue_size + alpha_size),
m_red_size(red_size),
m_green_size(green_size),
m_blue_size(blue_size),
m_alpha_size(alpha_size),
m_bind_to_tex_rgb(EGL_FALSE), //not supported for now
m_bind_to_tex_rgba(EGL_FALSE), //not supported for now
m_caveat(caveat),
m_config_id(config_id),
m_native_config_id(config_id),
m_frame_buffer_level(frame_buffer_level),
m_depth_size(depth_size),
m_max_pbuffer_width(max_pbuffer_width),
m_max_pbuffer_height(max_pbuffer_height),
m_max_pbuffer_size(max_pbuffer_size),
m_max_swap_interval(MAX_SWAP_INTERVAL),
m_min_swap_interval(MIN_SWAP_INTERVAL),
m_native_renderable(native_renderable),
m_renderable_type(renderable_type),
m_native_visual_id(native_visual_id),
m_native_visual_type(native_visual_type),
m_sample_buffers_num(samples_per_pixel > 0 ? 1 : 0),
m_samples_per_pixel(samples_per_pixel),
m_stencil_size(stencil_size),
m_surface_type(surface_type),
m_transparent_type(transparent_type),
m_trans_red_val(trans_red_val),
m_trans_green_val(trans_green_val),
m_trans_blue_val(trans_blue_val),
m_conformant(((red_size + green_size + blue_size + alpha_size > 0) &&
(caveat != EGL_NON_CONFORMANT_CONFIG)) ?
m_renderable_type : 0),
m_nativeFormat(frmt) {}
EglConfig::EglConfig(const EglConfig& conf) :
m_buffer_size(conf.m_buffer_size),
m_red_size(conf.m_red_size),
m_green_size(conf.m_green_size),
m_blue_size(conf.m_blue_size),
m_alpha_size(conf.m_alpha_size),
m_bind_to_tex_rgb(conf.m_bind_to_tex_rgb),
m_bind_to_tex_rgba(conf.m_bind_to_tex_rgba),
m_caveat(conf.m_caveat),
m_config_id(conf.m_config_id),
m_native_config_id(conf.m_native_config_id),
m_frame_buffer_level(conf.m_frame_buffer_level),
m_depth_size(conf.m_depth_size),
m_max_pbuffer_width(conf.m_max_pbuffer_width),
m_max_pbuffer_height(conf.m_max_pbuffer_height),
m_max_pbuffer_size(conf.m_max_pbuffer_size),
m_max_swap_interval(conf.m_max_swap_interval),
m_min_swap_interval(conf.m_min_swap_interval),
m_native_renderable(conf.m_native_renderable),
m_renderable_type(conf.m_renderable_type),
m_native_visual_id(conf.m_native_visual_id),
m_native_visual_type(conf.m_native_visual_type),
m_sample_buffers_num(conf.m_sample_buffers_num),
m_samples_per_pixel(conf.m_samples_per_pixel),
m_stencil_size(conf.m_stencil_size),
m_surface_type(conf.m_surface_type),
m_transparent_type(conf.m_transparent_type),
m_trans_red_val(conf.m_trans_red_val),
m_trans_green_val(conf.m_trans_green_val),
m_trans_blue_val(conf.m_trans_blue_val),
m_conformant(conf.m_conformant),
m_nativeFormat(conf.m_nativeFormat->clone()) {}
EglConfig::EglConfig(const EglConfig& conf,
EGLint config_id,
EGLint red_size,
EGLint green_size,
EGLint blue_size,
EGLint alpha_size) :
m_buffer_size(red_size + green_size + blue_size + alpha_size),
m_red_size(red_size),
m_green_size(green_size),
m_blue_size(blue_size),
m_alpha_size(alpha_size),
m_bind_to_tex_rgb(conf.m_bind_to_tex_rgb),
m_bind_to_tex_rgba(conf.m_bind_to_tex_rgba),
m_caveat(conf.m_caveat),
m_config_id(config_id),
m_native_config_id(conf.m_native_config_id),
m_frame_buffer_level(conf.m_frame_buffer_level),
m_depth_size(conf.m_depth_size),
m_max_pbuffer_width(conf.m_max_pbuffer_width),
m_max_pbuffer_height(conf.m_max_pbuffer_height),
m_max_pbuffer_size(conf.m_max_pbuffer_size),
m_max_swap_interval(conf.m_max_swap_interval),
m_min_swap_interval(conf.m_min_swap_interval),
m_native_renderable(conf.m_native_renderable),
m_renderable_type(conf.m_renderable_type),
m_native_visual_id(conf.m_native_visual_id),
m_native_visual_type(conf.m_native_visual_type),
m_sample_buffers_num(conf.m_sample_buffers_num),
m_samples_per_pixel(conf.m_samples_per_pixel),
m_stencil_size(conf.m_stencil_size),
m_surface_type(conf.m_surface_type),
m_transparent_type(conf.m_transparent_type),
m_trans_red_val(conf.m_trans_red_val),
m_trans_green_val(conf.m_trans_green_val),
m_trans_blue_val(conf.m_trans_blue_val),
m_conformant(conf.m_conformant),
m_nativeFormat(conf.m_nativeFormat->clone()) {};
bool EglConfig::getConfAttrib(EGLint attrib,EGLint* val) const {
switch(attrib) {
case EGL_BUFFER_SIZE:
*val = m_buffer_size;
break;
case EGL_RED_SIZE:
*val = m_red_size;
break;
case EGL_GREEN_SIZE:
*val = m_green_size;
break;
case EGL_BLUE_SIZE:
*val = m_blue_size;
break;
case EGL_ALPHA_SIZE:
*val = m_alpha_size;
break;
case EGL_BIND_TO_TEXTURE_RGB:
*val = m_bind_to_tex_rgb;
break;
case EGL_BIND_TO_TEXTURE_RGBA:
*val = m_bind_to_tex_rgba;
break;
case EGL_CONFIG_CAVEAT:
*val = m_caveat;
break;
case EGL_CONFIG_ID:
*val = m_config_id;
break;
case EGL_DEPTH_SIZE:
*val = m_depth_size;
break;
case EGL_LEVEL:
*val = m_frame_buffer_level;
break;
case EGL_MAX_PBUFFER_WIDTH:
*val = m_max_pbuffer_width;
break;
case EGL_MAX_PBUFFER_HEIGHT:
*val = m_max_pbuffer_height;
break;
case EGL_MAX_PBUFFER_PIXELS:
*val = m_max_pbuffer_size;
break;
case EGL_MAX_SWAP_INTERVAL:
*val = m_max_swap_interval;
break;
case EGL_MIN_SWAP_INTERVAL:
*val = m_min_swap_interval;
break;
case EGL_NATIVE_RENDERABLE:
*val = m_native_renderable;
break;
case EGL_NATIVE_VISUAL_ID:
*val = m_native_visual_id;
break;
case EGL_NATIVE_VISUAL_TYPE:
*val = m_native_visual_type;
break;
case EGL_RENDERABLE_TYPE:
*val = m_renderable_type;
break;
case EGL_SAMPLE_BUFFERS:
*val = m_sample_buffers_num;
break;
case EGL_SAMPLES:
*val = m_samples_per_pixel;
break;
case EGL_STENCIL_SIZE:
*val = m_stencil_size;
break;
case EGL_SURFACE_TYPE:
*val = m_surface_type;
break;
case EGL_TRANSPARENT_TYPE:
*val =m_transparent_type;
break;
case EGL_TRANSPARENT_RED_VALUE:
*val = m_trans_red_val;
break;
case EGL_TRANSPARENT_GREEN_VALUE:
*val = m_trans_green_val;
break;
case EGL_TRANSPARENT_BLUE_VALUE:
*val = m_trans_blue_val;
break;
case EGL_CONFORMANT:
*val = m_conformant;
break;
default:
return false;
}
return true;
}
// checking compitabilty between *this configuration and another configuration
// the compitability is checked againsed red,green,blue,buffer stencil and depth sizes
bool EglConfig::compatibleWith(const EglConfig& conf) const {
return m_buffer_size == conf.m_buffer_size &&
m_red_size == conf.m_red_size &&
m_green_size == conf.m_green_size &&
m_blue_size == conf.m_blue_size &&
m_depth_size == conf.m_depth_size &&
m_stencil_size == conf.m_stencil_size;
}
//following the sorting EGLconfig as in spec
bool EglConfig::operator<(const EglConfig& conf) const {
//0
if(m_conformant != conf.m_conformant) {
return m_conformant != 0; //We want the conformant ones first
}
//1
if(m_caveat != conf.m_caveat) {
return m_caveat < conf.m_caveat; // EGL_NONE < EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG
}
//2 TODO:
//3
if(m_buffer_size != conf.m_buffer_size) {
return m_buffer_size < conf.m_buffer_size;
}
//4
if(m_sample_buffers_num != conf.m_sample_buffers_num) {
return m_sample_buffers_num < conf.m_sample_buffers_num;
}
//5
if(m_samples_per_pixel != conf.m_samples_per_pixel) {
return m_samples_per_pixel < conf.m_samples_per_pixel;
}
//6
if(m_depth_size != conf.m_depth_size) {
return m_depth_size < conf.m_depth_size;
}
//7
if(m_stencil_size != conf.m_stencil_size) {
return m_stencil_size < conf.m_stencil_size;
}
//8 implementation defined
if(m_native_visual_type != conf.m_native_visual_type) {
return m_native_visual_type < conf.m_native_visual_type;
}
//9
return m_config_id < conf.m_config_id;
}
bool EglConfig::operator>=(const EglConfig& conf) const {
return !((*this) < conf);
}
#define CHECK_PROP(dummy,prop_name,op) \
if((dummy.prop_name != EGL_DONT_CARE) && (dummy.prop_name op prop_name)) return false;
#define CHECK_PROP_CAST(dummy,prop_name,op) \
if((((EGLint)dummy.prop_name) != EGL_DONT_CARE) && (dummy.prop_name op prop_name)) return false;
//checking if config stands for all the selection crateria of dummy as defined by EGL spec
bool EglConfig::chosen(const EglConfig& dummy) const {
//atleast
CHECK_PROP(dummy,m_buffer_size,>);
CHECK_PROP(dummy,m_red_size,>);
CHECK_PROP(dummy,m_green_size,>);
CHECK_PROP(dummy,m_blue_size,>);
CHECK_PROP(dummy,m_alpha_size,>);
CHECK_PROP(dummy,m_depth_size,>);
CHECK_PROP(dummy,m_stencil_size,>);
CHECK_PROP(dummy,m_sample_buffers_num,>);
CHECK_PROP(dummy,m_samples_per_pixel,>);
//exact
CHECK_PROP(dummy,m_frame_buffer_level,!=);
CHECK_PROP(dummy,m_config_id,!=);
CHECK_PROP(dummy,m_native_visual_type,!=);
CHECK_PROP(dummy,m_max_swap_interval ,!=);
CHECK_PROP(dummy,m_min_swap_interval ,!=);
CHECK_PROP(dummy,m_trans_red_val ,!=);
CHECK_PROP(dummy,m_trans_green_val ,!=);
CHECK_PROP(dummy,m_trans_blue_val ,!=);
//exact - when cast to EGLint is needed when comparing to EGL_DONT_CARE
CHECK_PROP_CAST(dummy,m_bind_to_tex_rgb ,!=);
CHECK_PROP_CAST(dummy,m_bind_to_tex_rgba,!=);
CHECK_PROP_CAST(dummy,m_caveat,!=);
CHECK_PROP_CAST(dummy,m_native_renderable ,!=);
CHECK_PROP_CAST(dummy,m_transparent_type ,!=);
//mask
if(dummy.m_surface_type != EGL_DONT_CARE &&
((dummy.m_surface_type & m_surface_type) != dummy.m_surface_type)) return false;
if(dummy.m_conformant != (EGLenum)EGL_DONT_CARE &&
((dummy.m_conformant & m_conformant) != dummy.m_conformant)) return false;
if(dummy.m_renderable_type != EGL_DONT_CARE &&
((dummy.m_renderable_type & m_renderable_type) != dummy.m_renderable_type)) return false;
//passed all checks
return true;
}

View file

@ -0,0 +1,148 @@
/*
* 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.
*/
#ifndef EGL_CONFIG_H
#define EGL_CONFIG_H
#include "EglOsApi.h"
#include <EGL/egl.h>
#include <list>
#define MIN_SWAP_INTERVAL 1
#define MAX_SWAP_INTERVAL 10
// A class used to model the content of an EGLConfig object.
// This is really a structure with several fields that can be queried
// individually with getConfigAttrib(), and compared for sorting according
// to the EGLConfig specification.
class EglConfig {
public:
// Return the value of a given attribute, identified by its name |attrib|
// (e.g. EGL_CONFIG_ID). On success, return true and sets |*val| to the
// attribute value. On failure (unknown |attrib| value), return false.
bool getConfAttrib(EGLint attrib, EGLint* val) const;
// Comparison operators used to sort EglConfig instances.
bool operator<(const EglConfig& conf) const;
bool operator>=(const EglConfig& conf) const;
// Return true iff this instance is compatible with |conf|, i.e. that
// they have the same red/green/blue/depth/stencil sizes.
bool compatibleWith(const EglConfig& conf) const; //compatibility
// Return true iff this instance matches the minimal requirements of
// another EglConfig |dummy|. Any attribute value in |dummy| that isn't
// EGL_DONT_CARE will be tested against the corresponding value in the
// instance.
bool chosen(const EglConfig& dummy) const;
// Return the EGL_SURFACE_TYPE value.
EGLint surfaceType() const { return m_surface_type;};
// Return the EGL_CONFIG_ID value.
EGLint id() const { return m_config_id; }
// Return the native configuration id. By default, this is the same as id()
// Except if the EglConfig was created with the overriding copy-constructor
// below. In which case nativeId() is the id() value of the source
// EglConfig, while id() will return the overriden value.
EGLint nativeId() const { return m_native_config_id; }
// Return the native pixel format for this config.
EglOS::PixelFormat* nativeFormat() const { return m_nativeFormat; }
// Constructor for a new instance, all values explicitly defined.
EglConfig(EGLint red_size,
EGLint green_size,
EGLint blue_size,
EGLint alpha_size,
EGLenum caveat,
EGLint config_id,
EGLint depth_size,
EGLint frame_buffer_level,
EGLint max_pbuffer_width,
EGLint max_pbuffer_height,
EGLint max_pbuffer_size,
EGLBoolean native_renderable,
EGLint renderable_type,
EGLint native_visual_id,
EGLint native_visual_type,
EGLint samples_per_pixel,
EGLint stencil_size,
EGLint surface_type,
EGLenum transparent_type,
EGLint trans_red_val,
EGLint trans_green_val,
EGLint trans_blue_val,
EglOS::PixelFormat* frmt);
// Copy-constructor.
EglConfig(const EglConfig& conf);
// A copy-constructor that allows one to override the configuration ID
// and red/green/blue/alpha sizes. Note that this is how one creates
// an EglConfig instance where nativeId() and id() return different
// values (see comment for nativeId()).
EglConfig(const EglConfig& conf,
EGLint config_id,
EGLint red_size,
EGLint green_size,
EGLint blue_size,
EGLint alpha_size);
// Destructor is required to get id of pixel format instance.
~EglConfig() {
delete m_nativeFormat;
}
private:
const EGLint m_buffer_size;
const EGLint m_red_size;
const EGLint m_green_size;
const EGLint m_blue_size;
const EGLint m_alpha_size;
const EGLBoolean m_bind_to_tex_rgb;
const EGLBoolean m_bind_to_tex_rgba;
const EGLenum m_caveat;
const EGLint m_config_id;
const EGLint m_native_config_id;
const EGLint m_frame_buffer_level;
const EGLint m_depth_size;
const EGLint m_max_pbuffer_width;
const EGLint m_max_pbuffer_height;
const EGLint m_max_pbuffer_size;
const EGLint m_max_swap_interval;
const EGLint m_min_swap_interval;
const EGLBoolean m_native_renderable;
const EGLint m_renderable_type;
const EGLint m_native_visual_id;
const EGLint m_native_visual_type;
const EGLint m_sample_buffers_num;
const EGLint m_samples_per_pixel;
const EGLint m_stencil_size;
const EGLint m_surface_type;
const EGLenum m_transparent_type;
const EGLint m_trans_red_val;
const EGLint m_trans_green_val;
const EGLint m_trans_blue_val;
const EGLenum m_conformant;
EglOS::PixelFormat* m_nativeFormat;
};
typedef std::list<EglConfig*> ConfigsList;
#endif

View file

@ -0,0 +1,96 @@
/*
* 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 "EglContext.h"
#include "EglDisplay.h"
#include "EglGlobalInfo.h"
#include "EglOsApi.h"
unsigned int EglContext::s_nextContextHndl = 0;
extern EglGlobalInfo* g_eglInfo; // defined in EglImp.cpp
bool EglContext::usingSurface(SurfacePtr surface) {
return surface.Ptr() == m_read.Ptr() || surface.Ptr() == m_draw.Ptr();
}
EglContext::EglContext(EglDisplay *dpy,
EglOS::Context* context,
ContextPtr shared_context,
EglConfig* config,
GLEScontext* glesCtx,
GLESVersion ver,
ObjectNameManager* mngr) :
m_dpy(dpy),
m_native(context),
m_config(config),
m_glesContext(glesCtx),
m_read(NULL),
m_draw(NULL),
m_version(ver),
m_mngr(mngr) {
m_shareGroup = shared_context.Ptr()?
mngr->attachShareGroup(context,shared_context->nativeType()):
mngr->createShareGroup(context);
m_hndl = ++s_nextContextHndl;
}
EglContext::~EglContext()
{
//
// remove the context in the underlying OS layer
//
m_dpy->nativeType()->destroyContext(m_native);
//
// call the client-api to remove the GLES context
//
g_eglInfo->getIface(version())->deleteGLESContext(m_glesContext);
if (m_mngr)
{
m_mngr->deleteShareGroup(m_native);
}
}
void EglContext::setSurfaces(SurfacePtr read,SurfacePtr draw)
{
m_read = read;
m_draw = draw;
}
bool EglContext::getAttrib(EGLint attrib,EGLint* value) {
switch(attrib) {
case EGL_CONFIG_ID:
*value = m_config->id();
break;
default:
return false;
}
return true;
}
bool EglContext::attachImage(unsigned int imageId,ImagePtr img){
if(m_attachedImages.find(imageId) == m_attachedImages.end()){
m_attachedImages[imageId] = img;
return true;
}
return false;
}
void EglContext::detachImage(unsigned int imageId){
m_attachedImages.erase(imageId);
}

View file

@ -0,0 +1,74 @@
/*
* 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.
*/
#ifndef EGL_CONTEXT_H
#define EGL_CONTEXT_H
#include "EglConfig.h"
#include "EglOsApi.h"
#include "EglSurface.h"
#include <GLcommon/GLutils.h>
#include <GLcommon/TranslatorIfaces.h>
#include <GLcommon/objectNameManager.h>
#include "emugl/common/smart_ptr.h"
#include <EGL/egl.h>
#include <map>
class EglContext;
typedef emugl::SmartPtr<EglContext> ContextPtr;
class EglDisplay;
class EglContext {
public:
EglContext(EglDisplay *dpy, EglOS::Context* context,ContextPtr shared_context,EglConfig* config,GLEScontext* glesCtx,GLESVersion ver,ObjectNameManager* mngr);
bool usingSurface(SurfacePtr surface);
EglOS::Context* nativeType() const { return m_native; }
bool getAttrib(EGLint attrib,EGLint* value);
SurfacePtr read(){ return m_read;};
SurfacePtr draw(){ return m_draw;};
ShareGroupPtr getShareGroup(){return m_shareGroup;}
EglConfig* getConfig(){ return m_config;};
GLESVersion version(){return m_version;};
GLEScontext* getGlesContext(){return m_glesContext;}
void setSurfaces(SurfacePtr read,SurfacePtr draw);
unsigned int getHndl(){return m_hndl;}
bool attachImage(unsigned int imageId,ImagePtr img);
void detachImage(unsigned int imageId);
~EglContext();
private:
static unsigned int s_nextContextHndl;
EglDisplay *m_dpy;
EglOS::Context* m_native;
EglConfig* m_config;
GLEScontext* m_glesContext;
ShareGroupPtr m_shareGroup;
SurfacePtr m_read;
SurfacePtr m_draw;
GLESVersion m_version;
ObjectNameManager *m_mngr;
unsigned int m_hndl;
ImagesHndlMap m_attachedImages;
};
#endif

View file

@ -0,0 +1,416 @@
/*
* 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 "EglDisplay.h"
#include "EglConfig.h"
#include "EglOsApi.h"
#include <GLcommon/GLutils.h>
EglDisplay::EglDisplay(EGLNativeDisplayType dpy,
EglOS::Display* idpy) :
m_dpy(dpy),
m_idpy(idpy),
m_initialized(false),
m_configInitialized(false),
m_nextEglImageId(0),
m_globalSharedContext(NULL)
{
m_manager[GLES_1_1] = new ObjectNameManager(&m_globalNameSpace);
m_manager[GLES_2_0] = new ObjectNameManager(&m_globalNameSpace);
};
EglDisplay::~EglDisplay() {
emugl::Mutex::AutoLock mutex(m_lock);
//
// Destroy the global context if one was created.
// (should be true for windows platform only)
//
if (m_globalSharedContext != NULL) {
m_idpy->destroyContext(m_globalSharedContext);
}
m_idpy->release();
for(ConfigsList::iterator it = m_configs.begin();
it != m_configs.end();
it++) {
delete *it;
}
delete m_manager[GLES_1_1];
delete m_manager[GLES_2_0];
delete m_idpy;
}
void EglDisplay::initialize(int renderableType) {
emugl::Mutex::AutoLock mutex(m_lock);
m_initialized = true;
initConfigurations(renderableType);
m_configInitialized = true;
}
bool EglDisplay::isInitialize() { return m_initialized;}
void EglDisplay::terminate(){
emugl::Mutex::AutoLock mutex(m_lock);
m_contexts.clear();
m_surfaces.clear();
m_initialized = false;
}
static bool compareEglConfigsPtrs(EglConfig* first,EglConfig* second) {
return *first < *second ;
}
void EglDisplay::addSimplePixelFormat(int red_size,
int green_size,
int blue_size,
int alpha_size) {
m_configs.sort(compareEglConfigsPtrs);
EGLConfig match;
EglConfig dummy(red_size,
green_size,
blue_size,
alpha_size, // RGB_565
EGL_DONT_CARE,
EGL_DONT_CARE,
16, // Depth
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
EGL_DONT_CARE,
NULL);
if(!doChooseConfigs(dummy, &match, 1))
{
return;
}
const EglConfig* config = (EglConfig*)match;
int bSize;
config->getConfAttrib(EGL_BUFFER_SIZE,&bSize);
if(bSize == 16)
{
return;
}
int max_config_id = 0;
for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) {
EGLint id;
(*it)->getConfAttrib(EGL_CONFIG_ID, &id);
if(id > max_config_id)
max_config_id = id;
}
EglConfig* newConfig = new EglConfig(*config,max_config_id+1,
red_size, green_size, blue_size,
alpha_size);
m_configs.push_back(newConfig);
}
void EglDisplay::addMissingConfigs() {
addSimplePixelFormat(5, 6, 5, 0); // RGB_565
addSimplePixelFormat(8, 8, 8, 0); // RGB_888
// (Host GPUs that are newer may not list RGB_888
// out of the box.)
}
void EglDisplay::initConfigurations(int renderableType) {
if (m_configInitialized) {
return;
}
m_idpy->queryConfigs(renderableType, addConfig, this);
addMissingConfigs();
m_configs.sort(compareEglConfigsPtrs);
#if EMUGL_DEBUG
for (ConfigsList::const_iterator it = m_configs.begin();
it != m_configs.end();
it++) {
EglConfig* config = *it;
EGLint red, green, blue, alpha, depth, stencil, renderable, surface;
config->getConfAttrib(EGL_RED_SIZE, &red);
config->getConfAttrib(EGL_GREEN_SIZE, &green);
config->getConfAttrib(EGL_BLUE_SIZE, &blue);
config->getConfAttrib(EGL_ALPHA_SIZE, &alpha);
config->getConfAttrib(EGL_DEPTH_SIZE, &depth);
config->getConfAttrib(EGL_STENCIL_SIZE, &stencil);
config->getConfAttrib(EGL_RENDERABLE_TYPE, &renderable);
config->getConfAttrib(EGL_SURFACE_TYPE, &surface);
}
#endif // EMUGL_DEBUG
}
EglConfig* EglDisplay::getConfig(EGLConfig conf) const {
emugl::Mutex::AutoLock mutex(m_lock);
for(ConfigsList::const_iterator it = m_configs.begin();
it != m_configs.end();
it++) {
if(static_cast<EGLConfig>(*it) == conf) {
return (*it);
}
}
return NULL;
}
SurfacePtr EglDisplay::getSurface(EGLSurface surface) const {
emugl::Mutex::AutoLock mutex(m_lock);
/* surface is "key" in map<unsigned int, SurfacePtr>. */
unsigned int hndl = SafeUIntFromPointer(surface);
SurfacesHndlMap::const_iterator it = m_surfaces.find(hndl);
return it != m_surfaces.end() ?
(*it).second :
SurfacePtr(NULL);
}
ContextPtr EglDisplay::getContext(EGLContext ctx) const {
emugl::Mutex::AutoLock mutex(m_lock);
/* ctx is "key" in map<unsigned int, ContextPtr>. */
unsigned int hndl = SafeUIntFromPointer(ctx);
ContextsHndlMap::const_iterator it = m_contexts.find(hndl);
return it != m_contexts.end() ?
(*it).second :
ContextPtr(NULL);
}
bool EglDisplay::removeSurface(EGLSurface s) {
emugl::Mutex::AutoLock mutex(m_lock);
/* s is "key" in map<unsigned int, SurfacePtr>. */
unsigned int hndl = SafeUIntFromPointer(s);
SurfacesHndlMap::iterator it = m_surfaces.find(hndl);
if(it != m_surfaces.end()) {
m_surfaces.erase(it);
return true;
}
return false;
}
bool EglDisplay::removeContext(EGLContext ctx) {
emugl::Mutex::AutoLock mutex(m_lock);
/* ctx is "key" in map<unsigned int, ContextPtr>. */
unsigned int hndl = SafeUIntFromPointer(ctx);
ContextsHndlMap::iterator it = m_contexts.find(hndl);
if(it != m_contexts.end()) {
m_contexts.erase(it);
return true;
}
return false;
}
bool EglDisplay::removeContext(ContextPtr ctx) {
emugl::Mutex::AutoLock mutex(m_lock);
ContextsHndlMap::iterator it;
for(it = m_contexts.begin(); it != m_contexts.end();it++) {
if((*it).second.Ptr() == ctx.Ptr()){
break;
}
}
if(it != m_contexts.end()) {
m_contexts.erase(it);
return true;
}
return false;
}
EglConfig* EglDisplay::getConfig(EGLint id) const {
emugl::Mutex::AutoLock mutex(m_lock);
for(ConfigsList::const_iterator it = m_configs.begin();
it != m_configs.end();
it++) {
if((*it)->id() == id) {
return (*it);
}
}
return NULL;
}
int EglDisplay::getConfigs(EGLConfig* configs,int config_size) const {
emugl::Mutex::AutoLock mutex(m_lock);
int i = 0;
for(ConfigsList::const_iterator it = m_configs.begin();
it != m_configs.end() && i < config_size;
i++, it++) {
configs[i] = static_cast<EGLConfig>(*it);
}
return i;
}
int EglDisplay::chooseConfigs(const EglConfig& dummy,
EGLConfig* configs,
int config_size) const {
emugl::Mutex::AutoLock mutex(m_lock);
return doChooseConfigs(dummy, configs, config_size);
}
int EglDisplay::doChooseConfigs(const EglConfig& dummy,
EGLConfig* configs,
int config_size) const {
int added = 0;
for(ConfigsList::const_iterator it = m_configs.begin();
it != m_configs.end() && (added < config_size || !configs);
it++) {
if( (*it)->chosen(dummy)){
if(configs) {
configs[added] = static_cast<EGLConfig>(*it);
}
added++;
}
}
//no need to sort since the configurations are saved already in sorted maner
return added;
}
EGLSurface EglDisplay::addSurface(SurfacePtr s ) {
emugl::Mutex::AutoLock mutex(m_lock);
unsigned int hndl = s.Ptr()->getHndl();
EGLSurface ret =reinterpret_cast<EGLSurface> (hndl);
if(m_surfaces.find(hndl) != m_surfaces.end()) {
return ret;
}
m_surfaces[hndl] = s;
return ret;
}
EGLContext EglDisplay::addContext(ContextPtr ctx ) {
emugl::Mutex::AutoLock mutex(m_lock);
unsigned int hndl = ctx.Ptr()->getHndl();
EGLContext ret = reinterpret_cast<EGLContext> (hndl);
if(m_contexts.find(hndl) != m_contexts.end()) {
return ret;
}
m_contexts[hndl] = ctx;
return ret;
}
EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) {
emugl::Mutex::AutoLock mutex(m_lock);
do { ++m_nextEglImageId; } while(m_nextEglImageId == 0);
img->imageId = m_nextEglImageId;
m_eglImages[m_nextEglImageId] = img;
return reinterpret_cast<EGLImageKHR>(m_nextEglImageId);
}
ImagePtr EglDisplay::getImage(EGLImageKHR img) const {
emugl::Mutex::AutoLock mutex(m_lock);
/* img is "key" in map<unsigned int, ImagePtr>. */
unsigned int hndl = SafeUIntFromPointer(img);
ImagesHndlMap::const_iterator i( m_eglImages.find(hndl) );
return (i != m_eglImages.end()) ? (*i).second :ImagePtr(NULL);
}
bool EglDisplay:: destroyImageKHR(EGLImageKHR img) {
emugl::Mutex::AutoLock mutex(m_lock);
/* img is "key" in map<unsigned int, ImagePtr>. */
unsigned int hndl = SafeUIntFromPointer(img);
ImagesHndlMap::iterator i( m_eglImages.find(hndl) );
if (i != m_eglImages.end())
{
m_eglImages.erase(i);
return true;
}
return false;
}
EglOS::Context* EglDisplay::getGlobalSharedContext() const {
emugl::Mutex::AutoLock mutex(m_lock);
#ifndef _WIN32
// find an existing OpenGL context to share with, if exist
EglOS::Context* ret =
(EglOS::Context*)m_manager[GLES_1_1]->getGlobalContext();
if (!ret)
ret = (EglOS::Context*)m_manager[GLES_2_0]->getGlobalContext();
return ret;
#else
if (!m_globalSharedContext) {
//
// On windows we create a dummy context to serve as the
// "global context" which all contexts share with.
// This is because on windows it is not possible to share
// with a context which is already current. This dummy context
// will never be current to any thread so it is safe to share with.
// Create that context using the first config
if (m_configs.size() < 1) {
// Should not happen! config list should be initialized at this point
return NULL;
}
EglConfig *cfg = (*m_configs.begin());
m_globalSharedContext = m_idpy->createContext(
cfg->nativeFormat(), NULL);
}
return m_globalSharedContext;
#endif
}
// static
void EglDisplay::addConfig(void* opaque, const EglOS::ConfigInfo* info) {
EglDisplay* display = static_cast<EglDisplay*>(opaque);
EglConfig* config = new EglConfig(
info->red_size,
info->green_size,
info->blue_size,
info->alpha_size,
info->caveat,
info->config_id,
info->depth_size,
info->frame_buffer_level,
info->max_pbuffer_width,
info->max_pbuffer_height,
info->max_pbuffer_size,
info->native_renderable,
info->renderable_type,
info->native_visual_id,
info->native_visual_type,
info->samples_per_pixel,
info->stencil_size,
info->surface_type,
info->transparent_type,
info->trans_red_val,
info->trans_green_val,
info->trans_blue_val,
info->frmt);
display->m_configs.push_back(config);
}

View file

@ -0,0 +1,116 @@
/*
* 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.
*/
#ifndef EGL_DISPLAY_H
#define EGL_DISPLAY_H
#include <list>
#include <map>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "emugl/common/mutex.h"
#include "emugl/common/smart_ptr.h"
#include "EglConfig.h"
#include "EglContext.h"
#include "EglOsApi.h"
#include "EglSurface.h"
#include "EglWindowSurface.h"
typedef std::map<unsigned int, ContextPtr> ContextsHndlMap;
typedef std::map<unsigned int, SurfacePtr> SurfacesHndlMap;
class EglDisplay {
public:
// Create new EglDisplay instance from a given native display |dpy|,
// with matching internal display |idpy|. If |isDefault| is true,
// this will be considered the default diplay.
EglDisplay(EGLNativeDisplayType dpy, EglOS::Display* idpy);
// Return the native display handle for this EglDisplay.
EGLNativeDisplayType getNativeDisplay() const { return m_dpy; }
// Return the native internal display handle for this EglDisplay.
EglOS::Display* nativeType() const { return m_idpy; }
// Return the number of known configurations for this EglDisplay.
int nConfigs() const { return m_configs.size(); }
// Write up to |config_size| EGLConfig values into the |configs| array.
// Return the number if values written.
int getConfigs(EGLConfig* configs,int config_size) const;
// Select all display configurations that match at least the values
// in |dummy|. If |configs| is NULL, this returns the number of all
// matching configs. Otherwise, this writes into |configs| up to
// |config_size| matching EGLConfig values, and returns their number.
int chooseConfigs(const EglConfig& dummy,
EGLConfig* configs,
int config_size) const;
// Return the EglConfig value that matches a given EGLConfig |conf|.
EglConfig* getConfig(EGLConfig conf) const;
// Return the EglConfig value that matches a given EGLConfig with
// EGL_CONFIG_ID value |id|.
EglConfig* getConfig(EGLint id) const;
EGLSurface addSurface(SurfacePtr s );
SurfacePtr getSurface(EGLSurface surface) const;
bool removeSurface(EGLSurface s);
EGLContext addContext(ContextPtr ctx );
ContextPtr getContext(EGLContext ctx) const;
bool removeContext(EGLContext ctx);
bool removeContext(ContextPtr ctx);
ObjectNameManager* getManager(GLESVersion ver) const { return m_manager[ver];}
~EglDisplay();
void initialize(int renderableType);
void terminate();
bool isInitialize();
ImagePtr getImage(EGLImageKHR img) const;
EGLImageKHR addImageKHR(ImagePtr);
bool destroyImageKHR(EGLImageKHR img);
EglOS::Context* getGlobalSharedContext() const;
private:
static void addConfig(void* opaque, const EglOS::ConfigInfo* configInfo);
int doChooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) const;
void addSimplePixelFormat(int red_size, int green_size, int blue_size, int alpha_size);
void addMissingConfigs(void);
void initConfigurations(int renderableType);
EGLNativeDisplayType m_dpy;
EglOS::Display* m_idpy;
bool m_initialized;
bool m_configInitialized;
ConfigsList m_configs;
ContextsHndlMap m_contexts;
SurfacesHndlMap m_surfaces;
GlobalNameSpace m_globalNameSpace;
ObjectNameManager* m_manager[MAX_GLES_VERSION];
mutable emugl::Mutex m_lock;
ImagesHndlMap m_eglImages;
unsigned int m_nextEglImageId;
mutable EglOS::Context* m_globalSharedContext;
};
#endif

View file

@ -0,0 +1,113 @@
/*
* 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 "EglGlobalInfo.h"
#include "ClientAPIExts.h"
#include "EglDisplay.h"
#include "EglOsApi.h"
#include "emugl/common/lazy_instance.h"
#include <string.h>
namespace {
// Use a LazyInstance to ensure thread-safe initialization.
emugl::LazyInstance<EglGlobalInfo> sSingleton = LAZY_INSTANCE_INIT;
} // namespace
// static
EglGlobalInfo* EglGlobalInfo::getInstance() {
return sSingleton.ptr();
}
EglGlobalInfo::EglGlobalInfo() :
m_displays(),
m_engine(NULL),
m_display(NULL),
m_lock() {
// TODO(digit): Choose alternate engine based on env. variable?
m_engine = EglOS::Engine::getHostInstance();
m_display = m_engine->getDefaultDisplay();
memset(m_gles_ifaces, 0, sizeof(m_gles_ifaces));
memset(m_gles_extFuncs_inited, 0, sizeof(m_gles_extFuncs_inited));
}
EglGlobalInfo::~EglGlobalInfo() {
for (size_t n = 0; n < m_displays.size(); ++n) {
delete m_displays[n];
}
}
EglDisplay* EglGlobalInfo::addDisplay(EGLNativeDisplayType dpy,
EglOS::Display* idpy) {
//search if it already exists.
emugl::Mutex::AutoLock mutex(m_lock);
for (size_t n = 0; n < m_displays.size(); ++n) {
if (m_displays[n]->getNativeDisplay() == dpy) {
return m_displays[n];
}
}
if (!idpy) {
return NULL;
}
EglDisplay* result = new EglDisplay(dpy, idpy);
m_displays.push_back(result);
return result;
}
bool EglGlobalInfo::removeDisplay(EGLDisplay dpy) {
emugl::Mutex::AutoLock mutex(m_lock);
for (size_t n = 0; n < m_displays.size(); ++n) {
if (m_displays[n] == static_cast<EglDisplay*>(dpy)) {
delete m_displays[n];
m_displays.remove(n);
return true;
}
}
return false;
}
EglDisplay* EglGlobalInfo::getDisplay(EGLNativeDisplayType dpy) const {
emugl::Mutex::AutoLock mutex(m_lock);
for (size_t n = 0; n < m_displays.size(); ++n) {
if (m_displays[n]->getNativeDisplay() == dpy) {
return m_displays[n];
}
}
return NULL;
}
EglDisplay* EglGlobalInfo::getDisplay(EGLDisplay dpy) const {
emugl::Mutex::AutoLock mutex(m_lock);
for (size_t n = 0; n < m_displays.size(); ++n) {
if (m_displays[n] == static_cast<EglDisplay*>(dpy)) {
return m_displays[n];
}
}
return NULL;
}
void EglGlobalInfo::initClientExtFuncTable(GLESVersion ver) {
emugl::Mutex::AutoLock mutex(m_lock);
if (!m_gles_extFuncs_inited[ver]) {
ClientAPIExts::initClientFuncs(m_gles_ifaces[ver], (int)ver - 1);
m_gles_extFuncs_inited[ver] = true;
}
}

View file

@ -0,0 +1,110 @@
/*
* 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.
*/
#ifndef EGL_GLOBAL_INFO
#define EGL_GLOBAL_INFO
#include "EglDisplay.h"
#include "EglConfig.h"
#include "EglContext.h"
#include "EglOsApi.h"
#include "emugl/common/lazy_instance.h"
#include "emugl/common/pod_vector.h"
#include "emugl/common/mutex.h"
#include <GLcommon/TranslatorIfaces.h>
#include <EGL/egl.h>
class EglDisplay;
// Holds all global information shared by the EGL implementation in a given
// process. This really amounts to:
//
// - A list of EglDisplay instances, each identified by an
// EGLNativeDisplayType and EglOS::Display*.
//
// - GLES interface function pointers for all supported GLES versions.
class EglGlobalInfo {
public:
// Returns a pointer to the process' single instance, which will be
// created on demand. This can be called multiple times, each call will
// increment an internal reference-count.
static EglGlobalInfo* getInstance();
// Create a new EglDisplay instance from an existing native |dpy| value.
// |idpy| is the corresponding native internal display type. See
// generateInternalDisplay() below to understand how they differ.
EglDisplay* addDisplay(EGLNativeDisplayType dpy,
EglOS::Display* idpy);
// Return the EglDisplay instance corresponding to a given native |dpy|
// value.
EglDisplay* getDisplay(EGLNativeDisplayType dpy) const;
// Return the EglDisplay instance corresponding to a given EGLDisplay |dpy|
// value. NULL if none matches.
EglDisplay* getDisplay(EGLDisplay dpy) const;
// Remove a given EGLDisplay identified by |dpy|.
bool removeDisplay(EGLDisplay dpy);
// Return the default native internal display handle.
EglOS::Display* getDefaultNativeDisplay() const {
return m_display;
};
// Return the default engine handle.
EglOS::Engine* getOsEngine() const {
return m_engine;
}
// Set the GLES interface pointer corresponding to a given GLES version.
// |iface| is a pointer to a structure containing function pointers
// related to a specific GLES version.
// |ver| is a version identifier, e.g. GLES_1_1 or GLES_2_0.
void setIface(const GLESiface* iface, GLESVersion ver) {
m_gles_ifaces[ver] = iface;
};
// Return the current GLES interface pointer for a given GLES version.
// |ver| is a version identifier, e.g. GLES_1_1 or GLES_2_0.
const GLESiface* getIface(GLESVersion ver) const {
return m_gles_ifaces[ver];
}
// Initialize the table of extension functions for a given GLES version
// |ver|. This must be called after setIface() for the corresponding
// version.
void initClientExtFuncTable(GLESVersion ver);
private:
EglGlobalInfo();
~EglGlobalInfo();
friend struct emugl::LazyInstance<EglGlobalInfo>;
emugl::PodVector<EglDisplay*> m_displays;
EglOS::Engine* m_engine;
EglOS::Display* m_display;
const GLESiface* m_gles_ifaces[MAX_GLES_VERSION];
bool m_gles_extFuncs_inited[MAX_GLES_VERSION];
mutable emugl::Mutex m_lock;
};
#endif

View file

@ -0,0 +1,981 @@
/*
* 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.
*/
#ifdef _WIN32
#undef EGLAPI
#define EGLAPI __declspec(dllexport)
#endif
#include "ThreadInfo.h"
#include <GLcommon/TranslatorIfaces.h>
#include "emugl/common/shared_library.h"
#include <OpenglCodecCommon/ErrorLog.h>
#include "EglWindowSurface.h"
#include "EglPbufferSurface.h"
#include "EglGlobalInfo.h"
#include "EglThreadInfo.h"
#include "EglValidate.h"
#include "EglDisplay.h"
#include "EglContext.h"
#include "EglConfig.h"
#include "EglOsApi.h"
#include "ClientAPIExts.h"
#include <EGL/egl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAJOR 1
#define MINOR 4
//declarations
EglImage *attachEGLImage(unsigned int imageId);
void detachEGLImage(unsigned int imageId);
GLEScontext* getGLESContext();
GlLibrary* getGlLibrary();
#define tls_thread EglThreadInfo::get()
EglGlobalInfo* g_eglInfo = NULL;
emugl::Mutex s_eglLock;
void initGlobalInfo()
{
emugl::Mutex::AutoLock mutex(s_eglLock);
if (!g_eglInfo) {
g_eglInfo = EglGlobalInfo::getInstance();
}
}
static const EGLiface s_eglIface = {
.getGLESContext = getGLESContext,
.eglAttachEGLImage = attachEGLImage,
.eglDetachEGLImage = detachEGLImage,
.eglGetGlLibrary = getGlLibrary,
};
static void initGLESx(GLESVersion version) {
const GLESiface* iface = g_eglInfo->getIface(version);
if (!iface) {
DBG("EGL failed to initialize GLESv%d; incompatible interface\n", version);
return;
}
iface->initGLESx();
}
/***************************************** supported extentions ***********************************************************************/
//extentions
#define EGL_EXTENTIONS 2
//decleration
extern "C" {
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image);
} // extern "C"
// extentions descriptors
static const ExtentionDescriptor s_eglExtentions[] = {
{"eglCreateImageKHR" ,
(__eglMustCastToProperFunctionPointerType)eglCreateImageKHR },
{"eglDestroyImageKHR",
(__eglMustCastToProperFunctionPointerType)eglDestroyImageKHR },
};
static const int s_eglExtentionsSize =
sizeof(s_eglExtentions) / sizeof(ExtentionDescriptor);
/****************************************************************************************************************************************/
//macros for accessing global egl info & tls objects
#define CURRENT_THREAD() do {} while (0);
#define RETURN_ERROR(ret,err) \
CURRENT_THREAD() \
if(tls_thread->getError() == EGL_SUCCESS) { \
tls_thread->setError(err); \
} \
return ret;
#define VALIDATE_DISPLAY_RETURN(EGLDisplay,ret) \
EglDisplay* dpy = g_eglInfo->getDisplay(EGLDisplay); \
if(!dpy){ \
RETURN_ERROR(ret,EGL_BAD_DISPLAY); \
} \
if(!dpy->isInitialize()) { \
RETURN_ERROR(ret,EGL_NOT_INITIALIZED); \
}
#define VALIDATE_CONFIG_RETURN(EGLConfig,ret) \
EglConfig* cfg = dpy->getConfig(EGLConfig); \
if(!cfg) { \
RETURN_ERROR(ret,EGL_BAD_CONFIG); \
}
#define VALIDATE_SURFACE_RETURN(EGLSurface,ret,varName) \
SurfacePtr varName = dpy->getSurface(EGLSurface); \
if(!varName.Ptr()) { \
RETURN_ERROR(ret,EGL_BAD_SURFACE); \
}
#define VALIDATE_CONTEXT_RETURN(EGLContext,ret) \
ContextPtr ctx = dpy->getContext(EGLContext); \
if(!ctx.Ptr()) { \
RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
}
#define VALIDATE_DISPLAY(EGLDisplay) \
VALIDATE_DISPLAY_RETURN(EGLDisplay,EGL_FALSE)
#define VALIDATE_CONFIG(EGLConfig) \
VALIDATE_CONFIG_RETURN(EGLConfig,EGL_FALSE)
#define VALIDATE_SURFACE(EGLSurface,varName) \
VALIDATE_SURFACE_RETURN(EGLSurface,EGL_FALSE,varName)
#define VALIDATE_CONTEXT(EGLContext) \
VALIDATE_CONTEXT_RETURN(EGLContext,EGL_FALSE)
GLEScontext* getGLESContext()
{
ThreadInfo* thread = getThreadInfo();
return thread->glesContext;
}
GlLibrary* getGlLibrary() {
return EglGlobalInfo::getInstance()->getOsEngine()->getGlLibrary();
}
EGLAPI EGLint EGLAPIENTRY eglGetError(void) {
CURRENT_THREAD();
EGLint err = tls_thread->getError();
tls_thread->setError(EGL_SUCCESS);
return err;
}
EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) {
EglDisplay* dpy = NULL;
EglOS::Display* internalDisplay = NULL;
initGlobalInfo();
if ((dpy = g_eglInfo->getDisplay(display_id))) {
return dpy;
}
if (display_id != EGL_DEFAULT_DISPLAY) {
return EGL_NO_DISPLAY;
}
internalDisplay = g_eglInfo->getDefaultNativeDisplay();
dpy = g_eglInfo->addDisplay(display_id,internalDisplay);
if(!dpy) {
return EGL_NO_DISPLAY;
}
return dpy;
}
#define TRANSLATOR_GETIFACE_NAME "__translator_getIfaces"
static __translator_getGLESIfaceFunc loadIfaces(const char* libName,
char* error,
size_t errorSize) {
emugl::SharedLibrary* libGLES = emugl::SharedLibrary::open(
libName, error, errorSize);
if (!libGLES) {
return NULL;
}
__translator_getGLESIfaceFunc func = (__translator_getGLESIfaceFunc)
libGLES->findSymbol(TRANSLATOR_GETIFACE_NAME);
if (!func) {
snprintf(error, errorSize, "Missing symbol %s",
TRANSLATOR_GETIFACE_NAME);
return NULL;
}
return func;
}
#define LIB_GLES_CM_NAME EMUGL_LIBNAME("GLES_CM_translator")
#define LIB_GLES_V2_NAME EMUGL_LIBNAME("GLES_V2_translator")
EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay display, EGLint *major, EGLint *minor) {
initGlobalInfo();
EglDisplay* dpy = g_eglInfo->getDisplay(display);
if(!dpy) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_DISPLAY);
}
if(major) *major = MAJOR;
if(minor) *minor = MINOR;
__translator_getGLESIfaceFunc func = NULL;
int renderableType = EGL_OPENGL_ES_BIT;
char error[256];
if(!g_eglInfo->getIface(GLES_1_1)) {
func = loadIfaces(LIB_GLES_CM_NAME, error, sizeof(error));
if (func) {
g_eglInfo->setIface(func(&s_eglIface),GLES_1_1);
} else {
fprintf(stderr, "%s: Could not find ifaces for GLES CM 1.1 [%s]\n",
__FUNCTION__, error);
return EGL_FALSE;
}
initGLESx(GLES_1_1);
}
if(!g_eglInfo->getIface(GLES_2_0)) {
func = loadIfaces(LIB_GLES_V2_NAME, error, sizeof(error));
if (func) {
renderableType |= EGL_OPENGL_ES2_BIT;
g_eglInfo->setIface(func(&s_eglIface),GLES_2_0);
} else {
fprintf(stderr, "%s: Could not find ifaces for GLES 2.0 [%s]\n",
__FUNCTION__, error);
}
initGLESx(GLES_2_0);
}
dpy->initialize(renderableType);
return EGL_TRUE;
}
EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay display) {
VALIDATE_DISPLAY(display);
dpy->terminate();
return EGL_TRUE;
}
EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay display, EGLint name) {
VALIDATE_DISPLAY(display);
static const char* vendor = "Google";
static const char* version = "1.4";
static const char* extensions = "EGL_KHR_image_base EGL_KHR_gl_texture_2D_image";
if(!EglValidate::stringName(name)) {
RETURN_ERROR(NULL,EGL_BAD_PARAMETER);
}
switch(name) {
case EGL_VENDOR:
return vendor;
case EGL_VERSION:
return version;
case EGL_EXTENSIONS:
return extensions;
}
return NULL;
}
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay display, EGLConfig *configs,
EGLint config_size, EGLint *num_config) {
VALIDATE_DISPLAY(display);
if(!num_config) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
}
if(configs == NULL) {
*num_config = dpy->nConfigs();
} else {
*num_config = dpy->getConfigs(configs,config_size);
}
return EGL_TRUE;
}
EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint *attrib_list,
EGLConfig *configs, EGLint config_size,
EGLint *num_config) {
VALIDATE_DISPLAY(display);
if(!num_config) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
}
//selection defaults
// NOTE: Some variables below are commented out to reduce compiler warnings.
// TODO(digit): Look if these variables are really needed or not, and if so
// fix the code to do it properly.
EGLint surface_type = EGL_WINDOW_BIT;
EGLint renderable_type = EGL_OPENGL_ES_BIT;
//EGLBoolean bind_to_tex_rgb = EGL_DONT_CARE;
//EGLBoolean bind_to_tex_rgba = EGL_DONT_CARE;
EGLenum caveat = EGL_DONT_CARE;
EGLint config_id = EGL_DONT_CARE;
EGLBoolean native_renderable = EGL_DONT_CARE;
EGLint native_visual_type = EGL_DONT_CARE;
//EGLint max_swap_interval = EGL_DONT_CARE;
//EGLint min_swap_interval = EGL_DONT_CARE;
EGLint trans_red_val = EGL_DONT_CARE;
EGLint trans_green_val = EGL_DONT_CARE;
EGLint trans_blue_val = EGL_DONT_CARE;
EGLenum transparent_type = EGL_NONE;
//EGLint buffer_size = 0;
EGLint red_size = 0;
EGLint green_size = 0;
EGLint blue_size = 0;
EGLint alpha_size = 0;
EGLint depth_size = 0;
EGLint frame_buffer_level = 0;
//EGLint sample_buffers_num = 0;
EGLint samples_per_pixel = 0;
EGLint stencil_size = 0;
if(!EglValidate::noAttribs(attrib_list)) { //there are attribs
int i = 0 ;
bool hasConfigId = false;
while(attrib_list[i] != EGL_NONE && !hasConfigId) {
switch(attrib_list[i]) {
case EGL_MAX_PBUFFER_WIDTH:
case EGL_MAX_PBUFFER_HEIGHT:
case EGL_MAX_PBUFFER_PIXELS:
case EGL_NATIVE_VISUAL_ID:
break; //we dont care from those selection crateria
case EGL_LEVEL:
if(attrib_list[i+1] == EGL_DONT_CARE) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
frame_buffer_level = attrib_list[i+1];
break;
case EGL_BUFFER_SIZE:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
//buffer_size = attrib_list[i+1];
break;
case EGL_RED_SIZE:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
red_size = attrib_list[i+1];
break;
case EGL_GREEN_SIZE:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
green_size = attrib_list[i+1];
break;
case EGL_BLUE_SIZE:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
blue_size = attrib_list[i+1];
break;
case EGL_ALPHA_SIZE:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
alpha_size = attrib_list[i+1];
break;
case EGL_BIND_TO_TEXTURE_RGB:
//bind_to_tex_rgb = attrib_list[i+1];
break;
case EGL_BIND_TO_TEXTURE_RGBA:
//bind_to_tex_rgba = attrib_list[i+1];
break;
case EGL_CONFIG_CAVEAT:
if(attrib_list[i+1] != EGL_NONE && attrib_list[i+1] != EGL_SLOW_CONFIG && attrib_list[i+1] != EGL_NON_CONFORMANT_CONFIG) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
caveat = attrib_list[i+1];
break;
case EGL_CONFIG_ID:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
config_id = attrib_list[i+1];
hasConfigId = true;
break;
case EGL_DEPTH_SIZE:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
depth_size = attrib_list[i+1];
break;
case EGL_MAX_SWAP_INTERVAL:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
//max_swap_interval = attrib_list[i+1];
break;
case EGL_MIN_SWAP_INTERVAL:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
//min_swap_interval = attrib_list[i+1];
break;
case EGL_NATIVE_RENDERABLE:
native_renderable = attrib_list[i+1];
break;
case EGL_RENDERABLE_TYPE:
renderable_type = attrib_list[i+1];
break;
case EGL_NATIVE_VISUAL_TYPE:
native_visual_type = attrib_list[i+1];
break;
if(attrib_list[i+1] < 0 || attrib_list[i+1] > 1 ) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
case EGL_SAMPLE_BUFFERS:
//sample_buffers_num = attrib_list[i+1];
break;
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
case EGL_SAMPLES:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
samples_per_pixel = attrib_list[i+1];
break;
case EGL_STENCIL_SIZE:
if(attrib_list[i+1] < 0) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
stencil_size = attrib_list[i+1];
break;
case EGL_SURFACE_TYPE:
surface_type = attrib_list[i+1];
break;
case EGL_TRANSPARENT_TYPE:
if(attrib_list[i+1] != EGL_NONE && attrib_list[i+1] != EGL_TRANSPARENT_RGB ) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
transparent_type = attrib_list[i+1];
break;
case EGL_TRANSPARENT_RED_VALUE:
trans_red_val = attrib_list[i+1];
break;
case EGL_TRANSPARENT_GREEN_VALUE:
trans_green_val = attrib_list[i+1];
break;
case EGL_TRANSPARENT_BLUE_VALUE:
trans_blue_val = attrib_list[i+1];
break;
default:
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
i+=2;
}
if(hasConfigId) {
EglConfig* pConfig = dpy->getConfig(config_id);
if(pConfig) {
if(configs) {
configs[0] = static_cast<EGLConfig>(pConfig);
}
*num_config = 1;
return EGL_TRUE;
} else {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
}
}
EglConfig dummy(red_size,green_size,blue_size,alpha_size,caveat,config_id,depth_size,
frame_buffer_level,0,0,0,native_renderable,renderable_type,0,native_visual_type,
samples_per_pixel,stencil_size,surface_type,transparent_type,
trans_red_val,trans_green_val,trans_blue_val,NULL);
*num_config = dpy->chooseConfigs(dummy,configs,config_size);
return EGL_TRUE;
}
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay display, EGLConfig config,
EGLint attribute, EGLint *value) {
VALIDATE_DISPLAY(display);
VALIDATE_CONFIG(config);
if(!EglValidate::confAttrib(attribute)){
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
return cfg->getConfAttrib(attribute,value)? EGL_TRUE:EGL_FALSE;
}
EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay display, EGLConfig config,
EGLNativeWindowType win,
const EGLint *attrib_list) {
VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE);
VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE);
if(!(cfg->surfaceType() & EGL_WINDOW_BIT)) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH);
}
if(!dpy->nativeType()->isValidNativeWin(win)) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_NATIVE_WINDOW);
}
if(!EglValidate::noAttribs(attrib_list)) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE);
}
if(EglWindowSurface::alreadyAssociatedWithConfig(win)) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC);
}
unsigned int width,height;
if(!dpy->nativeType()->checkWindowPixelFormatMatch(
win, cfg->nativeFormat(), &width, &height)) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC);
}
SurfacePtr wSurface(new EglWindowSurface(dpy, win,cfg,width,height));
if(!wSurface.Ptr()) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC);
}
return dpy->addSurface(wSurface);
}
EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(
EGLDisplay display,
EGLConfig config,
const EGLint *attrib_list) {
VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE);
VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE);
if(!(cfg->surfaceType() & EGL_PBUFFER_BIT)) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH);
}
SurfacePtr pbSurface(new EglPbufferSurface(dpy,cfg));
if(!pbSurface.Ptr()) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC);
}
if(!EglValidate::noAttribs(attrib_list)) { // There are attribs.
int i = 0 ;
while(attrib_list[i] != EGL_NONE) {
if(!pbSurface->setAttrib(attrib_list[i],attrib_list[i+1])) {
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE);
}
i+=2;
}
}
EGLint width, height, largest, texTarget, texFormat;
EglPbufferSurface* tmpPbSurfacePtr =
static_cast<EglPbufferSurface*>(pbSurface.Ptr());
tmpPbSurfacePtr->getDim(&width, &height, &largest);
tmpPbSurfacePtr->getTexInfo(&texTarget, &texFormat);
if(!EglValidate::pbufferAttribs(width,
height,
texFormat == EGL_NO_TEXTURE,
texTarget == EGL_NO_TEXTURE)) {
//TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad_value
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE);
}
EglOS::PbufferInfo pbinfo;
pbinfo.width = width;
pbinfo.height = height;
pbinfo.largest = largest;
pbinfo.target = texTarget;
pbinfo.format = texFormat;
tmpPbSurfacePtr->getAttrib(EGL_MIPMAP_TEXTURE, &pbinfo.hasMipmap);
EglOS::Surface* pb = dpy->nativeType()->createPbufferSurface(
cfg->nativeFormat(), &pbinfo);
if(!pb) {
//TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad value
RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE);
}
tmpPbSurfacePtr->setNativePbuffer(pb);
return dpy->addSurface(pbSurface);
}
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface) {
VALIDATE_DISPLAY(display);
SurfacePtr srfc = dpy->getSurface(surface);
if(!srfc.Ptr()) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE);
}
dpy->removeSurface(surface);
return EGL_TRUE;
}
EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay display, EGLSurface surface,
EGLint attribute, EGLint *value) {
VALIDATE_DISPLAY(display);
VALIDATE_SURFACE(surface,srfc);
if(!srfc->getAttrib(attribute,value)) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
return EGL_TRUE;
}
EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay display, EGLSurface surface,
EGLint attribute, EGLint value) {
VALIDATE_DISPLAY(display);
VALIDATE_SURFACE(surface,srfc);
if(!srfc->setAttrib(attribute,value)) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
return EGL_TRUE;
}
EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config,
EGLContext share_context,
const EGLint *attrib_list) {
VALIDATE_DISPLAY_RETURN(display,EGL_NO_CONTEXT);
VALIDATE_CONFIG_RETURN(config,EGL_NO_CONTEXT);
GLESVersion version = GLES_1_1;
if(!EglValidate::noAttribs(attrib_list)) {
int i = 0;
while(attrib_list[i] != EGL_NONE) {
switch(attrib_list[i]) {
case EGL_CONTEXT_CLIENT_VERSION:
if(attrib_list[i+1] == 2) {
version = GLES_2_0;
} else {
version = GLES_1_1;
}
break;
default:
RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
}
i+=2;
}
}
const GLESiface* iface = g_eglInfo->getIface(version);
GLEScontext* glesCtx = NULL;
if(iface) {
glesCtx = iface->createGLESContext();
} else { // there is no interface for this gles version
RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
}
ContextPtr sharedCtxPtr;
if(share_context != EGL_NO_CONTEXT) {
sharedCtxPtr = dpy->getContext(share_context);
if(!sharedCtxPtr.Ptr()) {
RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_CONTEXT);
}
}
EglOS::Context* globalSharedContext = dpy->getGlobalSharedContext();
EglOS::Context* nativeContext = dpy->nativeType()->createContext(
cfg->nativeFormat(), globalSharedContext);
if(nativeContext) {
ContextPtr ctx(new EglContext(dpy, nativeContext,sharedCtxPtr,cfg,glesCtx,version,dpy->getManager(version)));
return dpy->addContext(ctx);
} else {
iface->deleteGLESContext(glesCtx);
}
return EGL_NO_CONTEXT;
}
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay display, EGLContext context) {
VALIDATE_DISPLAY(display);
VALIDATE_CONTEXT(context);
dpy->removeContext(context);
return EGL_TRUE;
}
EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display,
EGLSurface draw,
EGLSurface read,
EGLContext context) {
VALIDATE_DISPLAY(display);
bool releaseContext = EglValidate::releaseContext(context, read, draw);
if(!releaseContext && EglValidate::badContextMatch(context, read, draw)) {
RETURN_ERROR(EGL_FALSE, EGL_BAD_MATCH);
}
ThreadInfo* thread = getThreadInfo();
ContextPtr prevCtx = thread->eglContext;
if(releaseContext) { //releasing current context
if(prevCtx.Ptr()) {
g_eglInfo->getIface(prevCtx->version())->flush();
if(!dpy->nativeType()->makeCurrent(NULL,NULL,NULL)) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS);
}
thread->updateInfo(ContextPtr(NULL),dpy,NULL,ShareGroupPtr(NULL),dpy->getManager(prevCtx->version()));
}
} else { //assining new context
VALIDATE_CONTEXT(context);
VALIDATE_SURFACE(draw,newDrawSrfc);
VALIDATE_SURFACE(read,newReadSrfc);
EglSurface* newDrawPtr = newDrawSrfc.Ptr();
EglSurface* newReadPtr = newReadSrfc.Ptr();
ContextPtr newCtx = ctx;
if (newCtx.Ptr() && prevCtx.Ptr()) {
if (newCtx.Ptr() == prevCtx.Ptr()) {
if (newDrawPtr == prevCtx->draw().Ptr() &&
newReadPtr == prevCtx->read().Ptr()) {
// nothing to do
return EGL_TRUE;
}
}
else {
// Make sure previous context is detached from surfaces
releaseContext = true;
}
}
//surfaces compatibility check
if(!((*ctx->getConfig()).compatibleWith((*newDrawPtr->getConfig()))) ||
!((*ctx->getConfig()).compatibleWith((*newReadPtr->getConfig())))) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_MATCH);
}
EglOS::Display* nativeDisplay = dpy->nativeType();
EglOS::Surface* nativeRead = newReadPtr->native();
EglOS::Surface* nativeDraw = newDrawPtr->native();
//checking native window validity
if(newReadPtr->type() == EglSurface::WINDOW &&
!nativeDisplay->isValidNativeWin(nativeRead)) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW);
}
if(newDrawPtr->type() == EglSurface::WINDOW &&
!nativeDisplay->isValidNativeWin(nativeDraw)) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW);
}
if(prevCtx.Ptr()) {
g_eglInfo->getIface(prevCtx->version())->flush();
}
if (!dpy->nativeType()->makeCurrent(
newReadPtr->native(),
newDrawPtr->native(),
newCtx->nativeType())) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS);
}
//TODO: handle the following errors
// EGL_BAD_CURRENT_SURFACE , EGL_CONTEXT_LOST , EGL_BAD_ACCESS
thread->updateInfo(newCtx,dpy,newCtx->getGlesContext(),newCtx->getShareGroup(),dpy->getManager(newCtx->version()));
newCtx->setSurfaces(newReadSrfc,newDrawSrfc);
g_eglInfo->getIface(newCtx->version())->initContext(newCtx->getGlesContext(),newCtx->getShareGroup());
// Initialize the GLES extension function table used in
// eglGetProcAddress for the context's GLES version if not
// yet initialized. We initialize it here to make sure we call the
// GLES getProcAddress after when a context is bound.
g_eglInfo->initClientExtFuncTable(newCtx->version());
}
// release previous context surface binding
if(prevCtx.Ptr() && releaseContext) {
prevCtx->setSurfaces(SurfacePtr(NULL),SurfacePtr(NULL));
}
return EGL_TRUE;
}
EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay display, EGLContext context,
EGLint attribute, EGLint *value) {
VALIDATE_DISPLAY(display);
VALIDATE_CONTEXT(context);
if(!ctx->getAttrib(attribute,value)){
RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
}
return EGL_TRUE;
}
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay display, EGLSurface surface) {
VALIDATE_DISPLAY(display);
VALIDATE_SURFACE(surface,Srfc);
ThreadInfo* thread = getThreadInfo();
ContextPtr currentCtx = thread->eglContext;
//if surface not window return
if(Srfc->type() != EglSurface::WINDOW){
RETURN_ERROR(EGL_TRUE,EGL_SUCCESS);
}
if(!currentCtx.Ptr() || !currentCtx->usingSurface(Srfc) ||
!dpy->nativeType()->isValidNativeWin(Srfc.Ptr()->native())) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE);
}
dpy->nativeType()->swapBuffers(Srfc->native());
return EGL_TRUE;
}
EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) {
ThreadInfo* thread = getThreadInfo();
EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay);
ContextPtr ctx = thread->eglContext;
if(dpy && ctx.Ptr()){
// This double check is required because a context might still be current after it is destroyed - in which case
// its handle should be invalid, that is EGL_NO_CONTEXT should be returned even though the context is current
EGLContext c = (EGLContext)SafePointerFromUInt(ctx->getHndl());
if(dpy->getContext(c).Ptr())
{
return c;
}
}
return EGL_NO_CONTEXT;
}
EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) {
if (!EglValidate::surfaceTarget(readdraw)) {
return EGL_NO_SURFACE;
}
ThreadInfo* thread = getThreadInfo();
EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay);
ContextPtr ctx = thread->eglContext;
if(dpy && ctx.Ptr()) {
SurfacePtr surface = readdraw == EGL_READ ? ctx->read() : ctx->draw();
if(surface.Ptr())
{
// This double check is required because a surface might still be
// current after it is destroyed - in which case its handle should
// be invalid, that is EGL_NO_SURFACE should be returned even
// though the surface is current.
EGLSurface s = (EGLSurface)SafePointerFromUInt(surface->getHndl());
surface = dpy->getSurface(s);
if(surface.Ptr())
{
return s;
}
}
}
return EGL_NO_SURFACE;
}
EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) {
ThreadInfo* thread = getThreadInfo();
return (thread->eglContext.Ptr()) ? thread->eglDisplay : EGL_NO_DISPLAY;
}
EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) {
if(!EglValidate::supportedApi(api)) {
RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
}
CURRENT_THREAD();
tls_thread->setApi(api);
return EGL_TRUE;
}
EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void) {
CURRENT_THREAD();
return tls_thread->getApi();
}
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) {
ThreadInfo* thread = getThreadInfo();
EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay);
return eglMakeCurrent(dpy,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
}
EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
eglGetProcAddress(const char *procname){
__eglMustCastToProperFunctionPointerType retVal = NULL;
initGlobalInfo();
if(!strncmp(procname,"egl",3)) { //EGL proc
for(int i=0;i < s_eglExtentionsSize;i++){
if(strcmp(procname,s_eglExtentions[i].name) == 0){
retVal = s_eglExtentions[i].address;
break;
}
}
}
else {
// Look at the clientAPI (GLES) supported extension
// function table.
retVal = ClientAPIExts::getProcAddress(procname);
}
return retVal;
}
/************************** KHR IMAGE *************************************************************/
EglImage *attachEGLImage(unsigned int imageId)
{
ThreadInfo* thread = getThreadInfo();
EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay);
ContextPtr ctx = thread->eglContext;
if (ctx.Ptr()) {
ImagePtr img = dpy->getImage(reinterpret_cast<EGLImageKHR>(imageId));
if(img.Ptr()) {
ctx->attachImage(imageId,img);
return img.Ptr();
}
}
return NULL;
}
void detachEGLImage(unsigned int imageId)
{
ThreadInfo* thread = getThreadInfo();
ContextPtr ctx = thread->eglContext;
if (ctx.Ptr()) {
ctx->detachImage(imageId);
}
}
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
VALIDATE_DISPLAY(display);
VALIDATE_CONTEXT(context);
// We only support EGL_GL_TEXTURE_2D images
if (target != EGL_GL_TEXTURE_2D_KHR) {
RETURN_ERROR(EGL_NO_IMAGE_KHR,EGL_BAD_PARAMETER);
}
ThreadInfo* thread = getThreadInfo();
ShareGroupPtr sg = thread->shareGroup;
if (sg.Ptr() != NULL) {
unsigned int globalTexName = sg->getGlobalName(TEXTURE, SafeUIntFromPointer(buffer));
if (!globalTexName) return EGL_NO_IMAGE_KHR;
ImagePtr img( new EglImage() );
if (img.Ptr() != NULL) {
ObjectDataPtr objData = sg->getObjectData(TEXTURE, SafeUIntFromPointer(buffer));
if (!objData.Ptr()) return EGL_NO_IMAGE_KHR;
TextureData *texData = (TextureData *)objData.Ptr();
if(!texData->width || !texData->height) return EGL_NO_IMAGE_KHR;
img->width = texData->width;
img->height = texData->height;
img->border = texData->border;
img->internalFormat = texData->internalFormat;
img->globalTexName = globalTexName;
return dpy->addImageKHR(img);
}
}
return EGL_NO_IMAGE_KHR;
}
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image)
{
VALIDATE_DISPLAY(display);
return dpy->destroyImageKHR(image) ? EGL_TRUE:EGL_FALSE;
}
/*********************************************************************************/

View file

@ -0,0 +1,188 @@
/*
* 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.
*/
#ifndef EGL_OS_API_H
#define EGL_OS_API_H
#include <EGL/egl.h>
#define PBUFFER_MAX_WIDTH 32767
#define PBUFFER_MAX_HEIGHT 32767
#define PBUFFER_MAX_PIXELS (PBUFFER_MAX_WIDTH * PBUFFER_MAX_HEIGHT)
class GlLibrary;
namespace EglOS {
// This header contains declaration used to abstract the underlying
// desktop GL library (or equivalent) that is being used by our EGL
// and GLES translation libraries.
// Use EglOS::Engine::getHostInstance() to retrieve an instance of the
// EglOS::Engine interface that matches the host display system.
//
// Alternate renderers (e.g. software-based Mesa) can also implement
// their own engine.
// Base class used to wrap various GL Surface types.
class Surface {
public:
typedef enum {
WINDOW = 0,
PBUFFER = 1,
} SurfaceType;
explicit Surface(SurfaceType type) : mType(type) {}
virtual ~Surface() {}
SurfaceType type() const { return mType; }
protected:
SurfaceType mType;
};
// An interface class for engine-specific implementation of a GL context.
class Context {
public:
Context() {}
virtual ~Context() {}
};
// Base class used to wrap engine-specific pixel format descriptors.
class PixelFormat {
public:
PixelFormat() {}
virtual ~PixelFormat() {}
virtual PixelFormat* clone() = 0;
};
// Small structure used to describe the properties of an engine-specific
// config.
struct ConfigInfo {
EGLint red_size;
EGLint green_size;
EGLint blue_size;
EGLint alpha_size;
EGLenum caveat;
EGLint config_id;
EGLint depth_size;
EGLint frame_buffer_level;
EGLint max_pbuffer_width;
EGLint max_pbuffer_height;
EGLint max_pbuffer_size;
EGLBoolean native_renderable;
EGLint renderable_type;
EGLint native_visual_id;
EGLint native_visual_type;
EGLint samples_per_pixel;
EGLint stencil_size;
EGLint surface_type;
EGLenum transparent_type;
EGLint trans_red_val;
EGLint trans_green_val;
EGLint trans_blue_val;
PixelFormat* frmt;
};
// A callback function type used with Display::queryConfig() to report to the
// caller a new host EGLConfig.
// |opaque| is an opaque value passed to queryConfig().
// All other parameters are config attributes.
// Note that ownership of |frmt| is transfered to the callback.
typedef void (AddConfigCallback)(void* opaque, const ConfigInfo* configInfo);
// Pbuffer description.
// |width| and |height| are its dimensions.
// |largest| is set to ask the largest pixek buffer (see GLX_LARGEST_PBUFFER).
// |format| is one of EGL_TEXTURE_RGB or EGL_TEXTURE_RGBA
// |target| is one of EGL_TEXTURE_2D or EGL_NO_TEXTURE.
// |hasMipmap| is true if the Pbuffer has mipmaps.
struct PbufferInfo {
EGLint width;
EGLint height;
EGLint largest;
EGLint format;
EGLint target;
EGLint hasMipmap;
};
// A class to model the engine-specific implementation of a GL display
// connection.
class Display {
public:
Display() {}
virtual ~Display() {}
virtual bool release() = 0;
virtual void queryConfigs(int renderableType,
AddConfigCallback* addConfigFunc,
void* addConfigOpaque) = 0;
virtual bool isValidNativeWin(Surface* win) = 0;
virtual bool isValidNativeWin(EGLNativeWindowType win) = 0;
virtual bool checkWindowPixelFormatMatch(EGLNativeWindowType win,
const PixelFormat* pixelFormat,
unsigned int* width,
unsigned int* height) = 0;
virtual Context* createContext(
const PixelFormat* pixelFormat, Context* sharedContext) = 0;
virtual bool destroyContext(Context* context) = 0;
virtual Surface* createPbufferSurface(
const PixelFormat* pixelFormat, const PbufferInfo* info) = 0;
virtual bool releasePbuffer(Surface* pb) = 0;
virtual bool makeCurrent(Surface* read,
Surface* draw,
Context* context) = 0;
virtual void swapBuffers(Surface* srfc) = 0;
};
// An interface class to model a specific underlying GL graphics subsystem
// or engine. Use getHost() to retrieve the implementation for the current
// host.
class Engine {
public:
Engine() {}
virtual ~Engine() {}
// Return a Display instance to the default display / window.
virtual Display* getDefaultDisplay() = 0;
// Return to engine-specific implementation of GlLibrary.
virtual GlLibrary* getGlLibrary() = 0;
// Create a new window surface. |wnd| is a host-specific window handle
// (e.g. a Windows HWND). A software renderer would always return NULL
// here.
virtual Surface* createWindowSurface(EGLNativeWindowType wnd) = 0;
// Retrieve the implementation for the current host. This can be called
// multiple times, and will initialize the engine on first call.
static Engine* getHostInstance();
};
} // namespace EglOS
#endif // EGL_OS_API_H

View file

@ -0,0 +1,395 @@
/*
* 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 "EglOsApi.h"
#include "MacNative.h"
#include "emugl/common/lazy_instance.h"
#include "emugl/common/shared_library.h"
#include "GLcommon/GLLibrary.h"
#include "OpenglCodecCommon/ErrorLog.h"
#include <list>
#define MAX_PBUFFER_MIPMAP_LEVEL 1
namespace {
class MacSurface : public EglOS::Surface {
public:
MacSurface(void* handle, SurfaceType type) :
Surface(type), m_handle(handle), m_hasMipmap(false) {}
void* handle() const { return m_handle; }
bool hasMipmap() const { return m_hasMipmap; }
void setHasMipmap(bool value) { m_hasMipmap = value; }
static MacSurface* from(EglOS::Surface* s) {
return static_cast<MacSurface*>(s);
}
private:
void* m_handle;
bool m_hasMipmap;
};
class MacContext : public EglOS::Context {
public:
explicit MacContext(void* context) : mContext(context) {}
virtual ~MacContext() {
nsDestroyContext(mContext);
}
void* context() const { return mContext; }
static void* from(EglOS::Context* c) {
return static_cast<MacContext*>(c)->context();
}
private:
void* mContext;
};
typedef std::list<void*> NativeFormatList;
NativeFormatList s_nativeFormats;
void initNativeConfigs(){
int nConfigs = getNumPixelFormats();
if (s_nativeFormats.empty()) {
for(int i = 0; i < nConfigs; i++) {
void* frmt = getPixelFormat(i);
if (frmt) {
s_nativeFormats.push_back(frmt);
}
}
}
}
class MacPixelFormat : public EglOS::PixelFormat {
public:
MacPixelFormat(void* handle, int redSize, int greenSize, int blueSize) :
mHandle(handle),
mRedSize(redSize),
mGreenSize(greenSize),
mBlueSize(blueSize) {}
EglOS::PixelFormat* clone() {
return new MacPixelFormat(mHandle, mRedSize, mGreenSize, mBlueSize);
}
void* handle() const { return mHandle; }
int redSize() const { return mRedSize; }
int greenSize() const { return mGreenSize; }
int blueSize() const { return mBlueSize; }
static const MacPixelFormat* from(const EglOS::PixelFormat* f) {
return static_cast<const MacPixelFormat*>(f);
}
private:
MacPixelFormat();
MacPixelFormat(const MacPixelFormat& other);
void* mHandle;
int mRedSize;
int mGreenSize;
int mBlueSize;
};
void pixelFormatToConfig(int index,
int renderableType,
void* frmt,
EglOS::AddConfigCallback addConfigFunc,
void* addConfigOpaque) {
EglOS::ConfigInfo info;
memset(&info, 0, sizeof(info));
EGLint doubleBuffer;
getPixelFormatAttrib(frmt, MAC_HAS_DOUBLE_BUFFER, &doubleBuffer);
if (!doubleBuffer) {
return; //pixel double buffer
}
EGLint window = 0, pbuffer = 0;
getPixelFormatAttrib(frmt, MAC_DRAW_TO_WINDOW, &window);
getPixelFormatAttrib(frmt, MAC_DRAW_TO_PBUFFER, &pbuffer);
info.surface_type = 0;
if (window) {
info.surface_type |= EGL_WINDOW_BIT;
}
if (pbuffer) {
info.surface_type |= EGL_PBUFFER_BIT;
}
if (!info.surface_type) {
return;
}
//default values
info.native_visual_id = 0;
info.native_visual_type = EGL_NONE;
info.caveat = EGL_NONE;
info.native_renderable = EGL_FALSE;
info.renderable_type = renderableType;
info.max_pbuffer_width = PBUFFER_MAX_WIDTH;
info.max_pbuffer_height = PBUFFER_MAX_HEIGHT;
info.max_pbuffer_size = PBUFFER_MAX_PIXELS;
info.samples_per_pixel = 0;
info.frame_buffer_level = 0;
info.trans_red_val = 0;
info.trans_green_val = 0;
info.trans_blue_val = 0;
info.transparent_type = EGL_NONE;
/* All configs can end up having an alpha channel even if none was requested.
* The default config chooser in GLSurfaceView will therefore not find any
* matching config. Thus, make sure alpha is zero (or at least signalled as
* zero to the calling EGL layer) for the configs where it was intended to
* be zero. */
if (getPixelFormatDefinitionAlpha(index) == 0) {
info.alpha_size = 0;
} else {
getPixelFormatAttrib(frmt, MAC_ALPHA_SIZE, &info.alpha_size);
}
getPixelFormatAttrib(frmt, MAC_DEPTH_SIZE, &info.depth_size);
getPixelFormatAttrib(frmt, MAC_STENCIL_SIZE, &info.stencil_size);
getPixelFormatAttrib(frmt, MAC_SAMPLES_PER_PIXEL, &info.samples_per_pixel);
//TODO: ask guy if it is OK
GLint colorSize = 0;
getPixelFormatAttrib(frmt, MAC_COLOR_SIZE, &colorSize);
info.red_size = info.green_size = info.blue_size = (colorSize / 4);
info.config_id = (EGLint) index;
info.frmt = new MacPixelFormat(
frmt, info.red_size, info.green_size, info.blue_size);
(*addConfigFunc)(addConfigOpaque, &info);
}
class MacDisplay : public EglOS::Display {
public:
explicit MacDisplay(EGLNativeDisplayType dpy) : mDpy(dpy) {}
virtual bool release() {
return true;
}
virtual void queryConfigs(int renderableType,
EglOS::AddConfigCallback* addConfigFunc,
void* addConfigOpaque) {
initNativeConfigs();
int i = 0;
for (NativeFormatList::iterator it = s_nativeFormats.begin();
it != s_nativeFormats.end();
it++) {
pixelFormatToConfig(i++,
renderableType,
*it,
addConfigFunc,
addConfigOpaque);
}
}
virtual bool isValidNativeWin(EglOS::Surface* win) {
if (win->type() != MacSurface::WINDOW) {
return false;
} else {
return isValidNativeWin(MacSurface::from(win)->handle());
}
}
virtual bool isValidNativeWin(EGLNativeWindowType win) {
unsigned int width, height;
return nsGetWinDims(win, &width, &height);
}
virtual bool checkWindowPixelFormatMatch(
EGLNativeWindowType win,
const EglOS::PixelFormat* pixelFormat,
unsigned int* width,
unsigned int* height) {
bool ret = nsGetWinDims(win, width, height);
const MacPixelFormat* format = MacPixelFormat::from(pixelFormat);
int r = format->redSize();
int g = format->greenSize();
int b = format->blueSize();
bool match = nsCheckColor(win, r + g + b);
return ret && match;
}
virtual EglOS::Context* createContext(
const EglOS::PixelFormat* pixelFormat,
EglOS::Context* sharedContext) {
void* macSharedContext =
sharedContext ? MacContext::from(sharedContext) : NULL;
return new MacContext(
nsCreateContext(MacPixelFormat::from(pixelFormat)->handle(),
macSharedContext));
}
virtual bool destroyContext(EglOS::Context* context) {
delete context;
return true;
}
virtual EglOS::Surface* createPbufferSurface(
const EglOS::PixelFormat* pixelFormat,
const EglOS::PbufferInfo* info) {
GLenum glTexFormat = GL_RGBA, glTexTarget = GL_TEXTURE_2D;
switch (info->format) {
case EGL_TEXTURE_RGB:
glTexFormat = GL_RGB;
break;
case EGL_TEXTURE_RGBA:
glTexFormat = GL_RGBA;
break;
}
EGLint maxMipmap = info->hasMipmap ? MAX_PBUFFER_MIPMAP_LEVEL : 0;
MacSurface* result = new MacSurface(
nsCreatePBuffer(
glTexTarget,
glTexFormat,
maxMipmap,
info->width,
info->height),
MacSurface::PBUFFER);
result->setHasMipmap(info->hasMipmap);
return result;
}
virtual bool releasePbuffer(EglOS::Surface* pb) {
if (pb) {
nsDestroyPBuffer(MacSurface::from(pb)->handle());
}
return true;
}
virtual bool makeCurrent(EglOS::Surface* read,
EglOS::Surface* draw,
EglOS::Context* ctx) {
// check for unbind
if (ctx == NULL && read == NULL && draw == NULL) {
nsWindowMakeCurrent(NULL, NULL);
return true;
}
else if (ctx == NULL || read == NULL || draw == NULL) {
// error !
return false;
}
//dont supporting diffrent read & draw surfaces on Mac
if (read != draw) {
return false;
}
switch (draw->type()) {
case MacSurface::WINDOW:
nsWindowMakeCurrent(MacContext::from(ctx),
MacSurface::from(draw)->handle());
break;
case MacSurface::PBUFFER:
{
MacSurface* macdraw = MacSurface::from(draw);
int mipmapLevel = macdraw->hasMipmap() ? MAX_PBUFFER_MIPMAP_LEVEL : 0;
nsPBufferMakeCurrent(MacContext::from(ctx),
macdraw->handle(), mipmapLevel);
break;
}
default:
return false;
}
return true;
}
virtual void swapBuffers(EglOS::Surface* srfc) {
nsSwapBuffers();
}
EGLNativeDisplayType dpy() const { return mDpy; }
private:
EGLNativeDisplayType mDpy;
};
class MacGlLibrary : public GlLibrary {
public:
MacGlLibrary() : mLib(NULL) {
static const char kLibName[] =
"/System/Library/Frameworks/OpenGL.framework/OpenGL";
char error[256];
mLib = emugl::SharedLibrary::open(kLibName, error, sizeof(error));
if (!mLib) {
ERR("%s: Could not open GL library %s [%s]\n",
__FUNCTION__, kLibName, error);
}
}
~MacGlLibrary() {
delete mLib;
}
// override
virtual GlFunctionPointer findSymbol(const char* name) {
if (!mLib) {
return NULL;
}
return reinterpret_cast<GlFunctionPointer>(mLib->findSymbol(name));
}
private:
emugl::SharedLibrary* mLib;
};
class MacEngine : public EglOS::Engine {
public:
MacEngine() : mGlLib() {}
virtual EglOS::Display* getDefaultDisplay() {
return new MacDisplay(0);
}
virtual GlLibrary* getGlLibrary() {
return &mGlLib;
}
virtual EglOS::Surface* createWindowSurface(EGLNativeWindowType wnd) {
return new MacSurface(wnd, MacSurface::WINDOW);
}
private:
MacGlLibrary mGlLib;
};
emugl::LazyInstance<MacEngine> sHostEngine = LAZY_INSTANCE_INIT;
} // namespace
// static
EglOS::Engine* EglOS::Engine::getHostInstance() {
return sHostEngine.ptr();
}

View file

@ -0,0 +1,464 @@
/*
* 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 "EglOsApi.h"
#include "emugl/common/lazy_instance.h"
#include "emugl/common/mutex.h"
#include "emugl/common/shared_library.h"
#include "GLcommon/GLLibrary.h"
#include "OpenglCodecCommon/ErrorLog.h"
#include <string.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
namespace {
typedef Display X11Display;
class ErrorHandler{
public:
ErrorHandler(EGLNativeDisplayType dpy);
~ErrorHandler();
int getLastError() const { return s_lastErrorCode; }
private:
static int s_lastErrorCode;
int (*m_oldErrorHandler)(Display *, XErrorEvent *);
static emugl::Mutex s_lock;
static int errorHandlerProc(EGLNativeDisplayType dpy,XErrorEvent* event);
};
// static
int ErrorHandler::s_lastErrorCode = 0;
// static
emugl::Mutex ErrorHandler::s_lock;
ErrorHandler::ErrorHandler(EGLNativeDisplayType dpy) {
emugl::Mutex::AutoLock mutex(s_lock);
XSync(dpy,False);
s_lastErrorCode = 0;
m_oldErrorHandler = XSetErrorHandler(errorHandlerProc);
}
ErrorHandler::~ErrorHandler() {
emugl::Mutex::AutoLock mutex(s_lock);
XSetErrorHandler(m_oldErrorHandler);
s_lastErrorCode = 0;
}
int ErrorHandler::errorHandlerProc(EGLNativeDisplayType dpy,
XErrorEvent* event) {
s_lastErrorCode = event->error_code;
return 0;
}
#define IS_SUCCESS(a) \
do { if (a != Success) return 0; } while (0)
#define EXIT_IF_FALSE(a) \
do { if (a != Success) return; } while (0)
// Implementation of EglOS::PixelFormat based on GLX.
class GlxPixelFormat : public EglOS::PixelFormat {
public:
explicit GlxPixelFormat(GLXFBConfig fbconfig) : mFbConfig(fbconfig) {}
virtual EglOS::PixelFormat* clone() {
return new GlxPixelFormat(mFbConfig);
}
GLXFBConfig fbConfig() const { return mFbConfig; }
static GLXFBConfig from(const EglOS::PixelFormat* f) {
return static_cast<const GlxPixelFormat*>(f)->fbConfig();
}
private:
GLXFBConfig mFbConfig;
};
void pixelFormatToConfig(EGLNativeDisplayType dpy,
int renderableType,
GLXFBConfig frmt,
EglOS::AddConfigCallback* addConfigFunc,
void* addConfigOpaque) {
EglOS::ConfigInfo info;
int tmp;
memset(&info, 0, sizeof(info));
EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_TRANSPARENT_TYPE, &tmp));
if (tmp == GLX_TRANSPARENT_INDEX) {
return; // not supporting transparent index
} else if (tmp == GLX_NONE) {
info.transparent_type = EGL_NONE;
info.trans_red_val = 0;
info.trans_green_val = 0;
info.trans_blue_val = 0;
} else {
info.transparent_type = EGL_TRANSPARENT_RGB;
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_TRANSPARENT_RED_VALUE, &info.trans_red_val));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_TRANSPARENT_GREEN_VALUE, &info.trans_green_val));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_TRANSPARENT_BLUE_VALUE, &info.trans_blue_val));
}
//
// filter out single buffer configurations
//
int doubleBuffer = 0;
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_DOUBLEBUFFER, &doubleBuffer));
if (!doubleBuffer) {
return;
}
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy ,frmt, GLX_RED_SIZE, &info.red_size));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy ,frmt, GLX_GREEN_SIZE, &info.green_size));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy ,frmt, GLX_BLUE_SIZE, &info.blue_size));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy ,frmt, GLX_ALPHA_SIZE, &info.alpha_size));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy ,frmt, GLX_DEPTH_SIZE, &info.depth_size));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy ,frmt, GLX_STENCIL_SIZE, &info.stencil_size));
info.renderable_type = renderableType;
int nativeRenderable = 0;
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_X_RENDERABLE, &nativeRenderable));
info.native_renderable = !!nativeRenderable;
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_X_VISUAL_TYPE, &info.native_visual_type));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_VISUAL_ID, &info.native_visual_id));
//supported surfaces types
info.surface_type = 0;
EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_DRAWABLE_TYPE, &tmp));
if (tmp & GLX_WINDOW_BIT && info.native_visual_id != 0) {
info.surface_type |= EGL_WINDOW_BIT;
} else {
info.native_visual_id = 0;
info.native_visual_type = EGL_NONE;
}
if (tmp & GLX_PBUFFER_BIT) {
info.surface_type |= EGL_PBUFFER_BIT;
}
info.caveat = 0;
EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_CONFIG_CAVEAT, &tmp));
if (tmp == GLX_NONE) {
info.caveat = EGL_NONE;
} else if (tmp == GLX_SLOW_CONFIG) {
info.caveat = EGL_SLOW_CONFIG;
} else if (tmp == GLX_NON_CONFORMANT_CONFIG) {
info.caveat = EGL_NON_CONFORMANT_CONFIG;
}
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_MAX_PBUFFER_WIDTH, &info.max_pbuffer_width));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_MAX_PBUFFER_HEIGHT, &info.max_pbuffer_height));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_MAX_PBUFFER_HEIGHT, &info.max_pbuffer_size));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_LEVEL, &info.frame_buffer_level));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_FBCONFIG_ID, &info.config_id));
EXIT_IF_FALSE(glXGetFBConfigAttrib(
dpy, frmt, GLX_SAMPLES, &info.samples_per_pixel));
//Filter out configs that do not support RGBA
EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_RENDER_TYPE, &tmp));
if (!(tmp & GLX_RGBA_BIT)) {
return;
}
info.frmt = new GlxPixelFormat(frmt);
(*addConfigFunc)(addConfigOpaque, &info);
}
// Implementation of EglOS::Surface based on GLX.
class GlxSurface : public EglOS::Surface {
public:
GlxSurface(GLXDrawable drawable, SurfaceType type) :
Surface(type), mDrawable(drawable) {}
GLXDrawable drawable() const { return mDrawable; }
// Helper routine to down-cast an EglOS::Surface and extract
// its drawable.
static GLXDrawable drawableFor(EglOS::Surface* surface) {
return static_cast<GlxSurface*>(surface)->drawable();
}
private:
GLXDrawable mDrawable;
};
// Implementation of EglOS::Context based on GLX.
class GlxContext : public EglOS::Context {
public:
explicit GlxContext(GLXContext context) : mContext(context) {}
GLXContext context() const { return mContext; }
static GLXContext contextFor(EglOS::Context* context) {
return static_cast<GlxContext*>(context)->context();
}
private:
GLXContext mContext;
};
// Implementation of EglOS::Display based on GLX.
class GlxDisplay : public EglOS::Display {
public:
explicit GlxDisplay(X11Display* disp) : mDisplay(disp) {}
virtual bool release() {
return XCloseDisplay(mDisplay);
}
virtual void queryConfigs(int renderableType,
EglOS::AddConfigCallback* addConfigFunc,
void* addConfigOpaque) {
int n;
GLXFBConfig* frmtList = glXGetFBConfigs(mDisplay, 0, &n);
for(int i = 0; i < n; i++) {
pixelFormatToConfig(
mDisplay,
renderableType,
frmtList[i],
addConfigFunc,
addConfigOpaque);
}
XFree(frmtList);
}
virtual bool isValidNativeWin(EglOS::Surface* win) {
if (!win) {
return false;
} else {
return isValidNativeWin(GlxSurface::drawableFor(win));
}
}
virtual bool isValidNativeWin(EGLNativeWindowType win) {
Window root;
int t;
unsigned int u;
ErrorHandler handler(mDisplay);
if (!XGetGeometry(mDisplay, win, &root, &t, &t, &u, &u, &u, &u)) {
return false;
}
return handler.getLastError() == 0;
}
virtual bool checkWindowPixelFormatMatch(
EGLNativeWindowType win,
const EglOS::PixelFormat* pixelFormat,
unsigned int* width,
unsigned int* height) {
//TODO: to check what does ATI & NVIDIA enforce on win pixelformat
unsigned int depth, configDepth, border;
int r, g, b, x, y;
GLXFBConfig fbconfig = GlxPixelFormat::from(pixelFormat);
IS_SUCCESS(glXGetFBConfigAttrib(
mDisplay, fbconfig, GLX_RED_SIZE, &r));
IS_SUCCESS(glXGetFBConfigAttrib(
mDisplay, fbconfig, GLX_GREEN_SIZE, &g));
IS_SUCCESS(glXGetFBConfigAttrib(
mDisplay, fbconfig, GLX_BLUE_SIZE, &b));
configDepth = r + g + b;
Window root;
if (!XGetGeometry(
mDisplay, win, &root, &x, &y, width, height, &border, &depth)) {
return false;
}
return depth >= configDepth;
}
virtual EglOS::Context* createContext(
const EglOS::PixelFormat* pixelFormat,
EglOS::Context* sharedContext) {
ErrorHandler handler(mDisplay);
GLXContext ctx = glXCreateNewContext(
mDisplay,
GlxPixelFormat::from(pixelFormat),
GLX_RGBA_TYPE,
sharedContext ? GlxContext::contextFor(sharedContext) : NULL,
true);
if (handler.getLastError()) {
return NULL;
}
return new GlxContext(ctx);
}
virtual bool destroyContext(EglOS::Context* context) {
glXDestroyContext(mDisplay, GlxContext::contextFor(context));
return true;
}
virtual EglOS::Surface* createPbufferSurface(
const EglOS::PixelFormat* pixelFormat,
const EglOS::PbufferInfo* info) {
const int attribs[] = {
GLX_PBUFFER_WIDTH, info->width,
GLX_PBUFFER_HEIGHT, info->height,
GLX_LARGEST_PBUFFER, info->largest,
None
};
GLXPbuffer pb = glXCreatePbuffer(
mDisplay,
GlxPixelFormat::from(pixelFormat),
attribs);
return pb ? new GlxSurface(pb, GlxSurface::PBUFFER) : NULL;
}
virtual bool releasePbuffer(EglOS::Surface* pb) {
if (!pb) {
return false;
} else {
glXDestroyPbuffer(mDisplay, GlxSurface::drawableFor(pb));
return true;
}
}
virtual bool makeCurrent(EglOS::Surface* read,
EglOS::Surface* draw,
EglOS::Context* context) {
ErrorHandler handler(mDisplay);
bool retval = false;
if (!context && !read && !draw) {
// unbind
retval = glXMakeContextCurrent(mDisplay, 0, 0, NULL);
}
else if (context && read && draw) {
retval = glXMakeContextCurrent(
mDisplay,
GlxSurface::drawableFor(draw),
GlxSurface::drawableFor(read),
GlxContext::contextFor(context));
}
return (handler.getLastError() == 0) && retval;
}
virtual void swapBuffers(EglOS::Surface* srfc) {
if (srfc) {
glXSwapBuffers(mDisplay, GlxSurface::drawableFor(srfc));
}
}
private:
X11Display* mDisplay;
};
class GlxLibrary : public GlLibrary {
public:
typedef GlFunctionPointer (ResolverFunc)(const char* name);
// Important: Use libGL.so.1 explicitly, because it will always link to
// the vendor-specific version of the library. libGL.so might in some
// cases, depending on bad ldconfig configurations, link to the wrapper
// lib that doesn't behave the same.
GlxLibrary() : mLib(NULL), mResolver(NULL) {
static const char kLibName[] = "libGL.so.1";
char error[256];
mLib = emugl::SharedLibrary::open(kLibName, error, sizeof(error));
if (!mLib) {
ERR("%s: Could not open GL library %s [%s]\n",
__FUNCTION__, kLibName, error);
return;
}
// NOTE: Don't use glXGetProcAddress here, only glXGetProcAddressARB
// is guaranteed to be supported by vendor-specific libraries.
static const char kResolverName[] = "glXGetProcAddressARB";
mResolver = reinterpret_cast<ResolverFunc*>(
mLib->findSymbol(kResolverName));
if (!mResolver) {
ERR("%s: Could not find resolver %s in %s\n",
__FUNCTION__, kResolverName, kLibName);
delete mLib;
mLib = NULL;
}
}
~GlxLibrary() {
delete mLib;
}
// override
virtual GlFunctionPointer findSymbol(const char* name) {
if (!mLib) {
return NULL;
}
GlFunctionPointer ret = (*mResolver)(name);
if (!ret) {
ret = reinterpret_cast<GlFunctionPointer>(mLib->findSymbol(name));
}
return ret;
}
private:
emugl::SharedLibrary* mLib;
ResolverFunc* mResolver;
};
class GlxEngine : public EglOS::Engine {
public:
GlxEngine() : mGlLib() {}
virtual EglOS::Display* getDefaultDisplay() {
return new GlxDisplay(XOpenDisplay(0));
}
virtual GlLibrary* getGlLibrary() {
return &mGlLib;
}
virtual EglOS::Surface* createWindowSurface(EGLNativeWindowType wnd) {
return new GlxSurface(wnd, GlxSurface::WINDOW);
}
private:
GlxLibrary mGlLib;
};
emugl::LazyInstance<GlxEngine> sHostEngine = LAZY_INSTANCE_INIT;
} // namespace
// static
EglOS::Engine* EglOS::Engine::getHostInstance() {
return sHostEngine.ptr();
}

View file

@ -0,0 +1,583 @@
/*
* 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.
*/
#define MIR_EGL_PLATFORM
#include "mir_support/shared_state.h"
#include "EglOsApi.h"
#include "emugl/common/lazy_instance.h"
#include "emugl/common/shared_library.h"
#include "GLcommon/GLLibrary.h"
#include "OpenglCodecCommon/ErrorLog.h"
#include <mirclient/mir_toolkit/mir_client_library.h>
#include <boost/throw_exception.hpp>
#include <stdexcept>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#define EXIT_IF_FALSE(a) \
do { if (!a) return; } while (0)
namespace {
class HostEglImpl {
public:
static HostEglImpl* get() {
static HostEglImpl *inst = new HostEglImpl;
return inst;
}
EGLint eglGetError() {
typedef EGLint (*_eglGetErrorFunc)();
static _eglGetErrorFunc _eglGetError;
if (!_eglGetError)
_eglGetError = reinterpret_cast<_eglGetErrorFunc>(lib_->findSymbol("eglGetError"));
return _eglGetError();
}
EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id) {
typedef EGLDisplay (*_eglGetDisplayFunc)(EGLNativeDisplayType display_id);
static _eglGetDisplayFunc _eglGetDisplay;
if (!_eglGetDisplay)
_eglGetDisplay = reinterpret_cast<_eglGetDisplayFunc>(lib_->findSymbol("eglGetDisplay"));
return _eglGetDisplay(display_id);
}
EGLBoolean eglInitialize(EGLDisplay display, EGLint *major, EGLint *minor) {
typedef EGLBoolean (*_eglInitializeFunc)(EGLDisplay display, EGLint *major, EGLint *minor);
static _eglInitializeFunc _eglInitialize = nullptr;
if (!_eglInitialize)
_eglInitialize = reinterpret_cast<_eglInitializeFunc>(lib_->findSymbol("eglInitialize"));
return _eglInitialize(display, major, minor);
}
EGLBoolean eglTerminate(EGLDisplay display) {
typedef EGLBoolean (*_eglTermianteFunc)(EGLDisplay display);
static _eglTermianteFunc _eglTerminate = nullptr;
if (!_eglTerminate)
_eglTerminate = reinterpret_cast<_eglTermianteFunc>(lib_->findSymbol("eglTerminate"));
return _eglTerminate(display);
}
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) {
typedef EGLContext (*_eglCreateContextFunc)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
static _eglCreateContextFunc _eglCreateContext = nullptr;
if (!_eglCreateContext)
_eglCreateContext = reinterpret_cast<_eglCreateContextFunc>(lib_->findSymbol("eglCreateContext"));
return _eglCreateContext(dpy, config, share_context, attrib_list);
}
EGLBoolean eglMakeCurrent(EGLDisplay display, EGLSurface read, EGLSurface draw, EGLContext context) {
typedef EGLBoolean (*_eglMakeCurrentFunc)(EGLDisplay display, EGLSurface read, EGLSurface draw, EGLContext context);
static _eglMakeCurrentFunc _eglMakeCurrent = nullptr;
if (!_eglMakeCurrent)
_eglMakeCurrent = reinterpret_cast<_eglMakeCurrentFunc>(lib_->findSymbol("eglMakeCurrent"));
return _eglMakeCurrent(display, read, draw, context);
}
EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) {
typedef EGLBoolean (*_eglGetConfigsFunc)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
static _eglGetConfigsFunc _eglGetConfigs = nullptr;
if (!_eglGetConfigs)
_eglGetConfigs = reinterpret_cast<_eglGetConfigsFunc>(lib_->findSymbol("eglGetConfigs"));
return _eglGetConfigs(dpy, configs, config_size, num_config);
}
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) {
typedef EGLSurface (*_eglCreatePbufferSurfaceFunc)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
static _eglCreatePbufferSurfaceFunc _eglCreatePbufferSurface = nullptr;
if (!_eglCreatePbufferSurface)
_eglCreatePbufferSurface = reinterpret_cast<_eglCreatePbufferSurfaceFunc>(lib_->findSymbol("eglCreatePbufferSurface"));
return _eglCreatePbufferSurface(dpy, config, attrib_list);
}
EGLBoolean eglDestroySurface(EGLDisplay display, EGLSurface surface) {
typedef EGLBoolean (*_eglDestroySurfaceFunc)(EGLDisplay display, EGLSurface surface);
static _eglDestroySurfaceFunc _eglDestroySurface = nullptr;
if (!_eglDestroySurface)
_eglDestroySurface = reinterpret_cast<_eglDestroySurfaceFunc>(lib_->findSymbol("eglDestroySurface"));
return _eglDestroySurface(display, surface);
}
EGLBoolean eglSwapBuffers(EGLDisplay display, EGLSurface surface) {
typedef EGLBoolean (*_eglSwapBuffersFunc)(EGLDisplay display, EGLSurface surface);
static _eglSwapBuffersFunc _eglSwapBuffers = nullptr;
if (!_eglSwapBuffers)
_eglSwapBuffers = reinterpret_cast<_eglSwapBuffersFunc>(lib_->findSymbol("eglSwapBuffers"));
return _eglSwapBuffers(display, surface);
}
EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) {
typedef EGLBoolean (*_eglGetConfigAttribFunc)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
static _eglGetConfigAttribFunc _eglGetConfigAttrib = nullptr;
if (!_eglGetConfigAttrib)
_eglGetConfigAttrib = reinterpret_cast<_eglGetConfigAttribFunc>(lib_->findSymbol("eglGetConfigAttrib"));
return _eglGetConfigAttrib(dpy, config, attribute, value);
}
EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, EGLNativeWindowType window, const EGLint *attribs) {
typedef EGLSurface (*_eglCreateWindowSurfaceFunc)(EGLDisplay display, EGLConfig config, EGLNativeWindowType window, const EGLint *attribs);
static _eglCreateWindowSurfaceFunc _eglCreateWindowSurface;
if (!_eglCreateWindowSurface)
_eglCreateWindowSurface = reinterpret_cast<_eglCreateWindowSurfaceFunc>(lib_->findSymbol("eglCreateWindowSurface"));
return _eglCreateWindowSurface(display, config, window, attribs);
}
private:
HostEglImpl() {
static const char kLibName[] = "libEGL.so.1";
char error[256];
lib_ = emugl::SharedLibrary::open(kLibName, error, sizeof(error));
if (!lib_) {
ERR("%s: Could not open host EGL library %s [%s]\n",
__FUNCTION__, kLibName, error);
return;
}
}
emugl::SharedLibrary *lib_;
};
class MirImplPixelFormat : public EglOS::PixelFormat {
public:
MirImplPixelFormat(EGLConfig config) :
config_(config) {
}
EGLConfig nativeFormat() const { return config_; }
virtual EglOS::PixelFormat* clone() {
return new MirImplPixelFormat(config_);
}
static const MirImplPixelFormat* from(const EglOS::PixelFormat *format) {
return static_cast<const MirImplPixelFormat*>(format);
}
EGLConfig config() const {
return config_;
}
private:
EGLConfig config_;
};
class MirImplSurface : public EglOS::Surface {
public:
MirImplSurface(SurfaceType type) :
Surface(type),
surface_(EGL_NO_SURFACE) {
}
static MirImplSurface* create_with_surface(EGLSurface surface) {
auto impl = new MirImplSurface(SurfaceType::PBUFFER);
impl->surface_ = surface;
return impl;
}
static MirImplSurface* create_with_native_window(EGLSurface surface) {
auto impl = new MirImplSurface(SurfaceType::WINDOW);
impl->surface_ = surface;
return impl;
}
EGLSurface drawable() {
return surface_;
}
void invalidate() {
surface_ = EGL_NO_SURFACE;
}
static MirImplSurface* from(EglOS::Surface *surface) {
if (!surface)
return nullptr;
return static_cast<MirImplSurface*>(surface);
}
private:
EGLSurface surface_;
EGLNativeWindowType native_window_;
};
class MirImplContext : public EglOS::Context {
public:
MirImplContext(EGLDisplay display, const MirImplPixelFormat *format, MirImplContext *shared_context) :
egl_display_(display),
egl_context_(EGL_NO_CONTEXT) {
EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
egl_context_ = HostEglImpl::get()->eglCreateContext(egl_display_,
format ? format->nativeFormat() : nullptr,
shared_context ? shared_context->nativeContext() : EGL_NO_CONTEXT,
context_attribs);
if (egl_context_ == EGL_NO_CONTEXT)
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create EGL context"));
}
bool release() {
if (!eglDestroyContext(egl_display_, egl_context_))
return false;
egl_display_ = EGL_NO_DISPLAY;
egl_context_ = EGL_NO_CONTEXT;
return true;
}
EGLContext nativeContext() const {
return egl_context_;
}
static MirImplContext* from(EglOS::Context *context) {
if (!context)
return nullptr;
return static_cast<MirImplContext*>(context);
}
private:
EGLDisplay egl_display_;
EGLContext egl_context_;
};
class MirImplDisplay : public EglOS::Display {
public:
explicit MirImplDisplay(MirConnection *connection) :
connection_(connection) {
if (!mir_connection_is_valid(connection_))
BOOST_THROW_EXCEPTION(std::runtime_error("Not connected to Mir server"));
egl_display_ = HostEglImpl::get()->eglGetDisplay(mir_connection_get_egl_native_display(connection_));
if (egl_display_ == EGL_NO_DISPLAY)
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to get EGL display"));
if (!HostEglImpl::get()->eglInitialize(egl_display_, nullptr, nullptr))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize EGL"));
}
virtual bool release() override {
HostEglImpl::get()->eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
HostEglImpl::get()->eglTerminate(egl_display_);
egl_display_ = EGL_NO_DISPLAY;
return true;
}
virtual void queryConfigs(int renderable_type, EglOS::AddConfigCallback *callback, void *user_data) override {
int num_configs = 0;
HostEglImpl::get()->eglGetConfigs(egl_display_, nullptr, 0, &num_configs);
auto configs = (EGLConfig*) calloc(num_configs, sizeof(EGLConfig));
int num_config_available = 0;
HostEglImpl::get()->eglGetConfigs(egl_display_, configs, num_configs, &num_config_available);
for (int n = 0; n < num_config_available; n++) {
EGLConfig config = configs[n];
EglOS::ConfigInfo info;
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_RED_SIZE, &info.red_size));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_GREEN_SIZE, &info.green_size));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_BLUE_SIZE, &info.blue_size));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_ALPHA_SIZE, &info.alpha_size));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_CONFIG_CAVEAT, &info.caveat));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_CONFIG_ID, &info.config_id));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_DEPTH_SIZE, &info.depth_size));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_LEVEL, &info.frame_buffer_level));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_MAX_PBUFFER_WIDTH, &info.max_pbuffer_width));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_MAX_PBUFFER_HEIGHT, &info.max_pbuffer_height));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_MAX_PBUFFER_PIXELS, &info.max_pbuffer_size));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_NATIVE_RENDERABLE, &info.native_renderable));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_RENDERABLE_TYPE, &info.renderable_type));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_NATIVE_VISUAL_ID, &info.native_visual_id));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_NATIVE_VISUAL_TYPE, &info.native_visual_type));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_SAMPLES, &info.samples_per_pixel));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_STENCIL_SIZE, &info.stencil_size));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_SURFACE_TYPE, &info.surface_type));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_TRANSPARENT_TYPE, &info.transparent_type));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_TRANSPARENT_RED_VALUE, &info.trans_red_val));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_TRANSPARENT_GREEN_VALUE, &info.trans_green_val));
EXIT_IF_FALSE(copy_egl_attrib(config, EGL_TRANSPARENT_BLUE_VALUE, &info.trans_blue_val));
info.frmt = new MirImplPixelFormat(config);
(*callback)(user_data, &info);
}
free(configs);
}
virtual bool isValidNativeWin(EglOS::Surface *surface) override {
if (!surface)
return false;
return surface->type() == EglOS::Surface::WINDOW;
}
virtual bool isValidNativeWin(EGLNativeWindowType window) override {
return true;
}
virtual bool checkWindowPixelFormatMatch(
EGLNativeWindowType window,
const EglOS::PixelFormat *format,
unsigned int *width,
unsigned int *height) override {
auto impl = MirImplPixelFormat::from(format);
EGLint r = 0, g = 0, b = 0;
if (!copy_egl_attrib(impl->nativeFormat(), EGL_RED_SIZE, &r))
return false;
if (!copy_egl_attrib(impl->nativeFormat(), EGL_GREEN_SIZE, &g))
return false;
if (!copy_egl_attrib(impl->nativeFormat(), EGL_BLUE_SIZE, &b))
return false;
const auto config_depth = r + g +b;
return true;
}
virtual EglOS::Context* createContext(const EglOS::PixelFormat *format, EglOS::Context *shared_context) override {
try {
return new MirImplContext(egl_display_,
MirImplPixelFormat::from(format),
MirImplContext::from(shared_context));
}
catch (std::exception &err) {
ERR("Failed to create EGL context: %s\n", err.what());
return nullptr;
}
}
virtual bool destroyContext(EglOS::Context *context) override {
if (!context)
return context;
return MirImplContext::from(context)->release();
}
virtual EglOS::Surface* createPbufferSurface(
const EglOS::PixelFormat* format,
const EglOS::PbufferInfo* info) override {
EGLint attribs[] = {
EGL_WIDTH, info->width,
EGL_HEIGHT, info->height,
EGL_LARGEST_PBUFFER, info->largest,
EGL_MIPMAP_TEXTURE, info->hasMipmap,
EGL_TEXTURE_TARGET, info->target,
EGL_NONE,
};
auto surface = HostEglImpl::get()->eglCreatePbufferSurface(egl_display_,
MirImplPixelFormat::from(format)->nativeFormat(),
attribs);
if (surface == EGL_NO_SURFACE)
return nullptr;
return MirImplSurface::create_with_surface(surface);
}
virtual bool releasePbuffer(EglOS::Surface *surface) override {
if (!surface)
return false;
auto impl = MirImplSurface::from(surface);
if (!impl)
return false;
if (!HostEglImpl::get()->eglDestroySurface(egl_display_, impl->drawable()))
return false;
impl->invalidate();
return true;
}
virtual bool makeCurrent(EglOS::Surface* input_surface,
EglOS::Surface* output_surface,
EglOS::Context* context) override {
bool success = false;
if (!input_surface && !output_surface && !context) {
success = HostEglImpl::get()->eglMakeCurrent(egl_display_,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
}
else if (input_surface && output_surface && context) {
success = HostEglImpl::get()->eglMakeCurrent(egl_display_,
MirImplSurface::from(input_surface)->drawable(),
MirImplSurface::from(output_surface)->drawable(),
MirImplContext::from(context)->nativeContext());
}
return success;
}
virtual void swapBuffers(EglOS::Surface *surface) override {
HostEglImpl::get()->eglSwapBuffers(egl_display_, MirImplSurface::from(surface)->drawable());
}
EGLDisplay display() const {
return egl_display_;
}
private:
template<typename T>
bool copy_egl_attrib(EGLConfig config, EGLint attribute, T *target) {
T value;
if (!HostEglImpl::get()->eglGetConfigAttrib(egl_display_, config, attribute, reinterpret_cast<EGLint*>(&value)))
return false;
*target = value;
return true;
}
MirConnection *connection_;
EGLDisplay egl_display_;
};
class MirImplGlLibrary : public GlLibrary {
public:
typedef GlFunctionPointer (ResolverFunc)(const char* name);
MirImplGlLibrary() {
static const char kLibName[] = "libGLESv2.so.2";
static const char kEGLLibName[] = "libEGL.so.1";
char error[256];
lib_ = emugl::SharedLibrary::open(kLibName, error, sizeof(error));
if (!lib_) {
ERR("%s: Could not open host GLESv2 library %s [%s]\n",
__FUNCTION__, kLibName, error);
return;
}
egl_lib_ = emugl::SharedLibrary::open(kEGLLibName, error, sizeof(error));
if (!lib_) {
ERR("%s: Could not open host EGL library %s [%s]\n",
__FUNCTION__, kEGLLibName, error);
return;
}
resolver_ = reinterpret_cast<ResolverFunc*>(egl_lib_->findSymbol("eglGetProcAddress"));
}
virtual GlFunctionPointer findSymbol(const char *name) override {
if (!lib_)
return nullptr;
ERR("Trying to resolved %s ...\n", name);
GlFunctionPointer symbol = nullptr;
if (resolver_)
symbol = (*resolver_)(name);
if (!symbol)
symbol = reinterpret_cast<GlFunctionPointer>(lib_->findSymbol(name));
ERR("-> %p\n", symbol);
return symbol;
}
private:
emugl::SharedLibrary *lib_;
emugl::SharedLibrary *egl_lib_;
ResolverFunc *resolver_;
};
class MirImplEngine : public EglOS::Engine {
public:
MirImplEngine() {
ERR("Initialized Mir EGL engine");
}
~MirImplEngine() {
}
virtual EglOS::Display* getDefaultDisplay() override {
mir::support::SharedState::get()->ensure_connection();
return new MirImplDisplay(mir::support::SharedState::get()->connection());
}
virtual GlLibrary* getGlLibrary() {
return &lib_;
}
virtual EglOS::Surface* createWindowSurface(EglOS::Display *display, EGLNativeWindowType window, EglOS::PixelFormat *format) override {
mir::support::SharedState::get()->ensure_connection();
auto surface = HostEglImpl::get()->eglCreateWindowSurface(
static_cast<MirImplDisplay*>(display)->display(),
static_cast<MirImplPixelFormat*>(format)->config(),
window,
nullptr);
return MirImplSurface::create_with_native_window(surface);
}
private:
MirImplGlLibrary lib_;
};
emugl::LazyInstance<MirImplEngine> sHostEngine = LAZY_INSTANCE_INIT;
}
EglOS::Engine* EglOS::Engine::getHostInstance() {
return sHostEngine.ptr();
}

View file

@ -0,0 +1,46 @@
/*
* 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 "EglOsApi.h"
#include "emugl/common/lazy_instance.h"
namespace {
class NullEngine : public EglOS::Engine {
public:
NullEngine() = default;
virtual EglOS::Display* getDefaultDisplay() override {
return nullptr;
}
virtual GlLibrary* getGlLibrary() {
return nullptr;
}
virtual EglOS::Surface* createWindowSurface(EGLNativeWindowType window) override {
return nullptr;
}
};
emugl::LazyInstance<NullEngine> sHostEngine = LAZY_INSTANCE_INIT;
}
#if 0
EglOS::Engine* EglOS::Engine::getHostInstance() {
return sHostEngine.ptr();
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,75 @@
/*
* 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 "EglPbufferSurface.h"
bool EglPbufferSurface::setAttrib(EGLint attrib,EGLint val) {
switch(attrib) {
case EGL_WIDTH:
if(val < 0) return false;
m_width = val;
break;
case EGL_HEIGHT:
if(val < 0) return false;
m_height = val;
break;
case EGL_LARGEST_PBUFFER:
m_largest = val;
break;
case EGL_TEXTURE_FORMAT:
if(val != EGL_NO_TEXTURE && val != EGL_TEXTURE_RGB && val != EGL_TEXTURE_RGBA) return false;
m_texFormat = val;
break;
case EGL_TEXTURE_TARGET:
if(val != EGL_NO_TEXTURE && val != EGL_TEXTURE_2D) return false;
m_texTarget = val;
break;
case EGL_MIPMAP_TEXTURE:
m_texMipmap = val;
break;
default:
return false;
}
return true;
}
bool EglPbufferSurface::getAttrib(EGLint attrib,EGLint* val) {
switch(attrib) {
case EGL_CONFIG_ID:
*val = m_config->id();
break;
case EGL_WIDTH:
*val = m_width;
break;
case EGL_HEIGHT:
*val = m_height;
break;
case EGL_LARGEST_PBUFFER:
*val = m_largest;
break;
case EGL_TEXTURE_FORMAT:
*val = m_texFormat;
break;
case EGL_TEXTURE_TARGET:
*val = m_texTarget;
break;
case EGL_MIPMAP_TEXTURE:
*val = m_texMipmap;
break;
default:
return false;
}
return true;
}

View file

@ -0,0 +1,49 @@
/*
* 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.
*/
#ifndef EGL_PBUFFER_SURFACE_H
#define EGL_PBUFFER_SURFACE_H
#include "EglSurface.h"
class EglDisplay;
class EglPbufferSurface:public EglSurface {
public:
EglPbufferSurface(EglDisplay *dpy, EglConfig* config):
EglSurface(dpy,PBUFFER,config,0,0),
m_texFormat(EGL_NO_TEXTURE),
m_texTarget(EGL_NO_TEXTURE),
m_texMipmap(EGL_FALSE),
m_largest(EGL_FALSE){};
void setNativePbuffer(EglOS::Surface* srfc) { m_native = srfc; }
bool setAttrib(EGLint attrib,EGLint val);
bool getAttrib(EGLint attrib,EGLint* val);
void getDim(EGLint* width,EGLint* height,EGLint* largest){
*width = m_width;
*height = m_height;
*largest = m_largest;
};
void getTexInfo(EGLint* format,EGLint* target){ *format = m_texFormat; *target = m_texTarget;}
private:
EGLint m_texFormat;
EGLint m_texTarget;
EGLint m_texMipmap;
EGLint m_largest;
};
#endif

View file

@ -0,0 +1,45 @@
/*
* 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 "EglSurface.h"
#include "EglDisplay.h"
#include "EglOsApi.h"
unsigned int EglSurface::s_nextSurfaceHndl = 0;
EglSurface::~EglSurface(){
if(m_type == EglSurface::PBUFFER) {
m_dpy->nativeType()->releasePbuffer(m_native);
}
delete m_native;
}
bool EglSurface::setAttrib(EGLint attrib,EGLint val) {
switch(attrib) {
case EGL_WIDTH:
case EGL_HEIGHT:
case EGL_LARGEST_PBUFFER:
case EGL_TEXTURE_FORMAT:
case EGL_TEXTURE_TARGET:
case EGL_MIPMAP_TEXTURE:
break;
default:
return false;
}
return true;
}

View file

@ -0,0 +1,89 @@
/*
* 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.
*/
#ifndef EGL_SURFACE_H
#define EGL_SURFACE_H
#include <map>
#include "EglConfig.h"
#include "EglOsApi.h"
#include "emugl/common/smart_ptr.h"
#include <EGL/egl.h>
class EglSurface;
typedef emugl::SmartPtr<EglSurface> SurfacePtr;
class EglDisplay;
class EglSurface {
public:
typedef enum {
WINDOW = 0,
PBUFFER = 1,
PIXMAP = 3
} ESurfaceType;
ESurfaceType type() const { return m_type; }
EglOS::Surface* native() const { return m_native; }
virtual bool setAttrib(EGLint attrib, EGLint val);
virtual bool getAttrib(EGLint attrib, EGLint* val) = 0;
void setDim(int width, int height) {
m_width = width;
m_height = height;
}
EglConfig* getConfig() const { return m_config; }
unsigned int getHndl() const { return m_hndl; }
virtual ~EglSurface();
private:
static unsigned int s_nextSurfaceHndl;
ESurfaceType m_type;
unsigned int m_hndl;
protected:
EglSurface(EglDisplay *dpy,
ESurfaceType type,
EglConfig* config,
EGLint width,
EGLint height) :
m_type(type),
m_config(config),
m_width(width),
m_height(height),
m_native(NULL),
m_dpy(dpy)
{
m_hndl = ++s_nextSurfaceHndl;
}
protected:
EglConfig* m_config;
EGLint m_width;
EGLint m_height;
EglOS::Surface* m_native;
EglDisplay *m_dpy;
};
#endif // EGL_SURFACE_H

View file

@ -0,0 +1,49 @@
/*
* 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 "EglThreadInfo.h"
#include "EglOsApi.h"
#include "emugl/common/lazy_instance.h"
#include "emugl/common/thread_store.h"
namespace {
class EglThreadInfoStore : public emugl::ThreadStore {
public:
EglThreadInfoStore() : emugl::ThreadStore(&destructor) {}
private:
static void destructor(void* value) {
delete static_cast<EglThreadInfo*>(value);
}
};
} // namespace
EglThreadInfo::EglThreadInfo() :
m_err(EGL_SUCCESS), m_api(EGL_OPENGL_ES_API) {}
static emugl::LazyInstance<EglThreadInfoStore> s_tls = LAZY_INSTANCE_INIT;
EglThreadInfo* EglThreadInfo::get(void)
{
EglThreadInfo *ti = static_cast<EglThreadInfo*>(s_tls->get());
if (!ti) {
ti = new EglThreadInfo();
s_tls->set(ti);
}
return ti;
}

View file

@ -0,0 +1,49 @@
/*
* 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.
*/
#ifndef EGL_THREAD_INFO_H
#define EGL_THREAD_INFO_H
#include <EGL/egl.h>
// Model thread-specific EGL state.
class EglThreadInfo {
public:
// Return the thread-specific instance of EglThreadInfo to the caller.
// The instance will be created on first call, and destroyed automatically
// when the thread exits.
static EglThreadInfo* get(void) __attribute__((const));
// Set the error code |err|. Default value is EGL_NO_ERROR.
void setError(EGLint err) { m_err = err; }
// Get the error code. Note that this doesn't change the value,
// unlike eglGetError() which resets it to EGL_NO_ERROR.
EGLint getError() const { return m_err; }
// Change the |api| value. Default is EGL_OPENGL_ES
void setApi(EGLenum api) { m_api = api; }
// Get the current API value.
EGLenum getApi() const { return m_api; }
private:
EglThreadInfo();
EGLint m_err;
EGLenum m_api;
};
#endif

View file

@ -0,0 +1,112 @@
/*
* 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 "EglValidate.h"
#include <GLcommon/GLutils.h>
// static
bool EglValidate::confAttrib(EGLint attrib) {
switch(attrib) {
case EGL_BUFFER_SIZE:
case EGL_RED_SIZE:
case EGL_GREEN_SIZE:
case EGL_BLUE_SIZE:
case EGL_ALPHA_SIZE:
case EGL_BIND_TO_TEXTURE_RGB:
case EGL_BIND_TO_TEXTURE_RGBA:
case EGL_CONFIG_CAVEAT:
case EGL_CONFIG_ID:
case EGL_DEPTH_SIZE:
case EGL_LEVEL:
case EGL_MAX_PBUFFER_WIDTH:
case EGL_MAX_PBUFFER_HEIGHT:
case EGL_MAX_PBUFFER_PIXELS:
case EGL_MAX_SWAP_INTERVAL:
case EGL_MIN_SWAP_INTERVAL:
case EGL_RENDERABLE_TYPE:
case EGL_NATIVE_RENDERABLE:
case EGL_NATIVE_VISUAL_ID:
case EGL_NATIVE_VISUAL_TYPE:
case EGL_SAMPLE_BUFFERS:
case EGL_SAMPLES:
case EGL_STENCIL_SIZE:
case EGL_SURFACE_TYPE:
case EGL_TRANSPARENT_TYPE:
case EGL_TRANSPARENT_RED_VALUE:
case EGL_TRANSPARENT_GREEN_VALUE:
case EGL_TRANSPARENT_BLUE_VALUE:
case EGL_CONFORMANT:
return true;
}
return false;
}
// static
bool EglValidate::noAttribs(const EGLint* attrib) {
return !attrib || attrib[0] == EGL_NONE ;
}
// static
bool EglValidate::pbufferAttribs(EGLint width,
EGLint height,
bool isTexFormatNoTex,
bool isTexTargetNoTex) {
if(!isTexFormatNoTex) {
if (!(isPowerOf2(width) && isPowerOf2(height))) {
return false;
}
}
return isTexFormatNoTex == isTexTargetNoTex ;
}
// static
bool EglValidate::releaseContext(EGLContext ctx,
EGLSurface s1,
EGLSurface s2) {
return (ctx == EGL_NO_CONTEXT) &&
(s1 == EGL_NO_SURFACE) &&
(s2 == EGL_NO_SURFACE);
}
// static
bool EglValidate::badContextMatch(EGLContext ctx,
EGLSurface s1,
EGLSurface s2) {
return (ctx != EGL_NO_CONTEXT)
? (s1 == EGL_NO_SURFACE || s2 == EGL_NO_SURFACE)
: (s1 != EGL_NO_SURFACE || s2 != EGL_NO_SURFACE);
}
// static
bool EglValidate::surfaceTarget(EGLint target) {
return target == EGL_READ || target == EGL_DRAW;
}
// static
bool EglValidate::engine(EGLint engine) {
return engine == EGL_CORE_NATIVE_ENGINE;
}
// static
bool EglValidate::stringName(EGLint name) {
return name == EGL_VENDOR ||
name == EGL_VERSION ||
name == EGL_EXTENSIONS;
}
// static
bool EglValidate::supportedApi(EGLenum api) {
return api == EGL_OPENGL_ES_API;
}

View file

@ -0,0 +1,75 @@
/*
* 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.
*/
#ifndef EGL_VALIDATE_H
#define EGL_VALIDATE_H
#include <EGL/egl.h>
class EglValidate {
public:
// Return true iff |attrib| is a valid EGLConfig attribute name.
static bool confAttrib(EGLint attrib);
// Return true iff |attrib| is NULL, or |attrib[0]| is EGL_NONE, which
// correspond to empty config attribute lists.
static bool noAttribs(const EGLint* attrib);
// Used to check that the config attributes used to create a new pbuffer
// are correct. |width| and |height| are the PBuffer's dimensions in
// pixels. |texFormatIsNoText| is true iff the PBuffer's texture format
// if EGL_NO_TEXTURE. |texTargetIsNoTex| is true iff the PBuffer's target
// is EGL_NO_TEXTURE.
static bool pbufferAttribs(EGLint width,
EGLint height,
bool texFormatIsNoTex,
bool texTargetIsNoTex);
// Return true if |ctx| is EGL_NO_CONTEXT, and both |draw| and |read|
// are EGL_NO_SURFACE. This corresponds to an eglMakeCurrent operation
// used to release the current context and draw/read surfaces at the
// same time.
static bool releaseContext(EGLContext ctx,
EGLSurface draw,
EGLSurface read);
// Return true if the values of |ctx|, |draw| and |read| do _not_ match
// the following rules:
//
// - If |ctx| is EGL_NO_CONTEXT, then |draw| and |read| must be
// EGL_NO_SURFACE.
//
// - If |ctx| is not EGL_NO_CONTEXT, then |draw| and |read| must not
// be EGL_NO_SURFACE.
//
static bool badContextMatch(EGLContext ctx,
EGLSurface draw,
EGLSurface read);
// Returns true iff |target| is either EGL_DRAW or EGL_READ.
static bool surfaceTarget(EGLint target);
// Returns true iff |engine| is EGL_CORE_NATIVE_RENDERER
static bool engine(EGLint engine);
// Returns true iff |name| is the attribute name of a string, e.g.
// EGL_VENDOR, EGL_VERSION or EGL_EXTENSIONS.
static bool stringName(EGLint name);
// Returns true iff |api| is the value of a supported API, e.g.
// EGL_OPENGL_ES_API.
static bool supportedApi(EGLenum api);
};
#endif

View file

@ -0,0 +1,69 @@
/*
* 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 "EglWindowSurface.h"
#include "EglGlobalInfo.h"
#include "EglOsApi.h"
#include "emugl/common/lazy_instance.h"
// this static member is accessed from a function registered in onexit()
// for the emulator cleanup. As all static C++ objects are also being freed
// from a system handler registered in onexit(), we can't have a class object
// by value here - it would be prone to unstable deinitialization order issue;
static emugl::LazyInstance<std::set<EGLNativeWindowType>>
s_associatedWins = LAZY_INSTANCE_INIT;
bool EglWindowSurface::alreadyAssociatedWithConfig(EGLNativeWindowType win) {
return s_associatedWins.get().find(win) != s_associatedWins.get().end();
}
EglWindowSurface::EglWindowSurface(EglDisplay* dpy,
EGLNativeWindowType win,
EglConfig* config,
unsigned int width,
unsigned int height) :
EglSurface(dpy, WINDOW, config, width, height),
m_win(win) {
s_associatedWins.get().insert(win);
EglOS::Engine* engine = EglGlobalInfo::getInstance()->getOsEngine();
m_native = engine->createWindowSurface(win);
}
EglWindowSurface::~EglWindowSurface() {
s_associatedWins.get().erase(m_win);
}
bool EglWindowSurface::getAttrib(EGLint attrib,EGLint* val) {
switch(attrib) {
case EGL_CONFIG_ID:
*val = m_config->id();
break;
case EGL_WIDTH:
*val = m_width;
break;
case EGL_HEIGHT:
*val = m_height;
break;
case EGL_LARGEST_PBUFFER:
case EGL_TEXTURE_FORMAT:
case EGL_TEXTURE_TARGET:
case EGL_MIPMAP_TEXTURE:
break;
default:
return false;
}
return true;
}

View file

@ -0,0 +1,44 @@
/*
* 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.
*/
#ifndef EGL_WINDOW_SURFACE_H
#define EGL_WINDOW_SURFACE_H
#include <set>
#include <EGL/egl.h>
#include "EglSurface.h"
#include "EglConfig.h"
class EglDisplay;
class EglWindowSurface: public EglSurface {
public:
EglWindowSurface(EglDisplay* dpy,
EGLNativeWindowType win,
EglConfig* config,
unsigned width,
unsigned int height);
~EglWindowSurface();
bool getAttrib(EGLint attrib,EGLint* val);
static bool alreadyAssociatedWithConfig(EGLNativeWindowType win);
private:
EGLNativeWindowType m_win;
};
#endif // EGL_WINDOW_SURFACE_H

View file

@ -0,0 +1,53 @@
/*
* Copyright 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.
*/
#ifndef MAC_NATIVE_H
#define MAC_NATIVE_H
#include <OpenGL/gl.h>
typedef enum { // Mac equivalence
MAC_HAS_DOUBLE_BUFFER = 5, // NSOpenGLPFADoubleBuffer
MAC_DRAW_TO_WINDOW = 80, // NSOpenGLPFAWindow
MAC_DRAW_TO_PBUFFER = 90, // NSOpenGLPFAPixelBuffer
MAC_SAMPLES_PER_PIXEL = 56, // NSOpenGLPFASamples
MAC_COLOR_SIZE = 8, // NSOpenGLPFAColorSize
MAC_ALPHA_SIZE = 11, // NSOpenGLPFAAlphaSize
MAC_DEPTH_SIZE = 12, // NSOpenGLPFADepthSize
MAC_STENCIL_SIZE = 13 // NSOpenGLPFAStencilSize
} MacPixelFormatAttribs;
extern "C"{
int getNumPixelFormats();
void* getPixelFormat(int i);
int getPixelFormatDefinitionAlpha(int i);
void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val);
void* nsCreateContext(void* format,void* share);
void nsWindowMakeCurrent(void* context,void* nativeWin);
void nsPBufferMakeCurrent(void* context,void* nativePBuffer,int level);
void nsSwapBuffers();
void nsSwapInterval(int *interval);
void nsDestroyContext(void* context);
void* nsCreatePBuffer(GLenum target,GLenum format,int maxMip,int width,int height);
void nsDestroyPBuffer(void* pbuffer);
bool nsGetWinDims(void* win,unsigned int* width,unsigned int* height);
bool nsCheckColor(void* win,int colorSize);
}
#endif

View file

@ -0,0 +1,207 @@
/*
* 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 <stdio.h>
#include <Cocoa/Cocoa.h>
#include <OpenGL/OpenGL.h>
#include "MacPixelFormatsAttribs.h"
//
// EmuGLContext inherit from NSOpenGLContext
// and adds binding state for the context to know
// if it was last bounded to a pbuffer or a window.
// This is because after the context was bounded to
// a Pbuffer, before we bind it to a window we must
// release it form the pbuffer by calling the
// clearDrawable method. We do not want to call clearDrawable
// more than really needed since when it is called at a time
// that a window is bounded to the context it will clear the
// window content causing flickering effect.
// Thererfore we call clearDrawable only when we bind the context
// to a window and it was previously bound to a Pbuffer.
//
@interface EmuGLContext : NSOpenGLContext {
@private
int boundToPbuffer;
int boundToWin;
}
- (id) initWithFormat:(NSOpenGLPixelFormat *)pixelFormat shareContext:(NSOpenGLContext *)share;
- (void) preBind:(int)forPbuffer;
@end
@implementation EmuGLContext
- (id) initWithFormat:(NSOpenGLPixelFormat *)pixelFormat shareContext:(NSOpenGLContext *)share
{
self = [super initWithFormat:pixelFormat shareContext:share];
if (self != nil) {
boundToPbuffer = 0;
boundToWin = 0;
}
return self;
}
- (void) preBind:(int)forPbuffer
{
if ((!forPbuffer && boundToPbuffer)) {
[self clearDrawable];
}
boundToPbuffer = forPbuffer;
boundToWin = !boundToPbuffer;
}
@end
int getNumPixelFormats(){
int size;
NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size);
return size;
}
void* getPixelFormat(int i){
int size;
NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size);
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrib_lists[i]];
}
int getPixelFormatDefinitionAlpha(int i) {
int size;
NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size);
NSOpenGLPixelFormatAttribute* attribs = attrib_lists[i];
while (*attribs) {
switch (*attribs) {
// These are the ones that take a value, according to the current
// NSOpenGLPixelFormat docs
case NSOpenGLPFAAuxBuffers:
case NSOpenGLPFAColorSize:
case NSOpenGLPFADepthSize:
case NSOpenGLPFAStencilSize:
case NSOpenGLPFAAccumSize:
case NSOpenGLPFARendererID:
case NSOpenGLPFAScreenMask:
attribs += 2;
break;
case NSOpenGLPFAAlphaSize:
return attribs[1];
break;
// All other attributes are boolean attributes that don't take a value
default:
attribs++;
}
}
return 0;
}
void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val){
NSOpenGLPixelFormat *frmt = (NSOpenGLPixelFormat *)pixelFormat;
[frmt getValues:val forAttribute:attrib forVirtualScreen:0];
}
void* nsCreateContext(void* format,void* share){
NSOpenGLPixelFormat* frmt = (NSOpenGLPixelFormat*)format;
return [[EmuGLContext alloc] initWithFormat:frmt shareContext:share];
}
void nsPBufferMakeCurrent(void* context,void* nativePBuffer,int level){
EmuGLContext* ctx = (EmuGLContext *)context;
NSOpenGLPixelBuffer* pbuff = (NSOpenGLPixelBuffer *)nativePBuffer;
if(ctx == nil){
[NSOpenGLContext clearCurrentContext];
} else {
if(pbuff != nil){
[ctx preBind:1];
[ctx setPixelBuffer:pbuff cubeMapFace:0 mipMapLevel:level currentVirtualScreen:0];
[ctx makeCurrentContext];
}
}
}
void nsWindowMakeCurrent(void* context,void* nativeWin){
EmuGLContext* ctx = (EmuGLContext *)context;
NSView* win = (NSView *)nativeWin;
if(ctx == nil){
[NSOpenGLContext clearCurrentContext];
} else if (win != nil) {
[ctx preBind:0];
[ctx setView: win];
[ctx makeCurrentContext];
}
}
void nsSwapBuffers(){
NSOpenGLContext* ctx = [NSOpenGLContext currentContext];
if(ctx != nil){
[ctx flushBuffer];
}
}
void nsSwapInterval(int *interval){
NSOpenGLContext* ctx = [NSOpenGLContext currentContext];
if( ctx != nil){
[ctx setValues:interval forParameter:NSOpenGLCPSwapInterval];
}
}
void nsDestroyContext(void* context){
EmuGLContext *ctx = (EmuGLContext*)context;
if(ctx != nil){
[ctx release];
}
}
void* nsCreatePBuffer(GLenum target,GLenum format,int maxMip,int width,int height){
return [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target
textureInternalFormat:format
textureMaxMipMapLevel:maxMip
pixelsWide:width pixelsHigh:height];
}
void nsDestroyPBuffer(void* pbuffer){
NSOpenGLPixelBuffer *pbuf = (NSOpenGLPixelBuffer*)pbuffer;
if(pbuf != nil){
[pbuf release];
}
}
bool nsGetWinDims(void* win,unsigned int* width,unsigned int* height){
NSView* view = (NSView*)win;
if(view != nil){
NSRect rect = [view bounds];
*width = rect.size.width;
*height = rect.size.height;
return true;
}
return false;
}
bool nsCheckColor(void* win,int colorSize){
NSView* view = (NSView*)win;
if(view != nil){
NSWindow* wnd = [view window];
if(wnd != nil){
NSWindowDepth limit = [wnd depthLimit];
NSWindowDepth defaultLimit = [NSWindow defaultDepthLimit];
int depth = (limit != 0) ? NSBitsPerPixelFromDepth(limit):
NSBitsPerPixelFromDepth(defaultLimit);
return depth >= colorSize;
}
}
return false;
}

View file

@ -0,0 +1,23 @@
/*
* Copyright 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.
*/
#ifndef MAC_PIXELS_FORMATS_ATTRIBS_H
#define MAC_PIXELS_FORMATS_ATTRIBS_H
#include <Cocoa/Cocoa.h>
NSOpenGLPixelFormatAttribute** getPixelFormatsAttributes(int* size);
#endif

View file

@ -0,0 +1,214 @@
/*
* Copyright 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 "MacPixelFormatsAttribs.h"
static NSOpenGLPixelFormatAttribute attrs32_1[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,32,
NSOpenGLPFADepthSize ,24,
NSOpenGLPFAStencilSize ,8,
0
};
static NSOpenGLPixelFormatAttribute attrs32_2[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,32,
NSOpenGLPFAAlphaSize ,8,
NSOpenGLPFADepthSize ,24,
NSOpenGLPFAStencilSize ,8,
0
};
static NSOpenGLPixelFormatAttribute attrs32_3[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,32,
NSOpenGLPFAAlphaSize ,8,
0
};
static NSOpenGLPixelFormatAttribute attrs32_4[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,32,
0
};
static NSOpenGLPixelFormatAttribute attrs32_5[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,32,
NSOpenGLPFADepthSize ,24,
NSOpenGLPFASamples ,2,
0
};
static NSOpenGLPixelFormatAttribute attrs32_6[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,32,
NSOpenGLPFADepthSize ,24,
NSOpenGLPFASamples ,4,
0
};
static NSOpenGLPixelFormatAttribute attrs32_7[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,32,
NSOpenGLPFAAlphaSize ,8,
NSOpenGLPFADepthSize ,24,
NSOpenGLPFAStencilSize ,8,
NSOpenGLPFASamples ,4,
0
};
static NSOpenGLPixelFormatAttribute attrs16_1[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,16,
NSOpenGLPFADepthSize ,24,
0
};
static NSOpenGLPixelFormatAttribute attrs16_2[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,16,
NSOpenGLPFADepthSize ,24,
NSOpenGLPFAStencilSize ,8,
0
};
static NSOpenGLPixelFormatAttribute attrs64_1[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,64,
NSOpenGLPFAAlphaSize ,16,
0
};
static NSOpenGLPixelFormatAttribute attrs64_2[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,64,
NSOpenGLPFAAlphaSize ,16,
NSOpenGLPFADepthSize ,24,
NSOpenGLPFAStencilSize ,8,
0
};
static NSOpenGLPixelFormatAttribute attrs64_3[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,64,
NSOpenGLPFAAlphaSize ,16,
NSOpenGLPFADepthSize ,24,
0
};
static NSOpenGLPixelFormatAttribute attrs64_4[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,64,
NSOpenGLPFADepthSize ,24,
0
};
static NSOpenGLPixelFormatAttribute attrs64_5[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,64,
NSOpenGLPFADepthSize ,24,
NSOpenGLPFAStencilSize ,8,
0
};
static NSOpenGLPixelFormatAttribute attrs128_1[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,128,
NSOpenGLPFAAlphaSize ,32,
0
};
static NSOpenGLPixelFormatAttribute attrs128_2[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAWindow,
NSOpenGLPFAPixelBuffer,
NSOpenGLPFAColorSize ,128,
NSOpenGLPFAAlphaSize ,32,
NSOpenGLPFADepthSize ,24,
0
};
NSOpenGLPixelFormatAttribute** getPixelFormatsAttributes(int* size){
static NSOpenGLPixelFormatAttribute* arr[] =
{
attrs16_1,
attrs16_2,
attrs32_1,
attrs32_2,
attrs32_3,
attrs32_4,
attrs32_5,
attrs32_6,
attrs32_7,
attrs64_1,
attrs64_2,
attrs64_3,
attrs64_4,
attrs64_5,
attrs128_1,
attrs128_2
};
*size = sizeof(arr)/sizeof(arr[0]);
return arr;
}

View file

@ -0,0 +1,83 @@
/*
* 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 "ThreadInfo.h"
#include "emugl/common/lazy_instance.h"
#include "emugl/common/thread_store.h"
#include <stdio.h>
// Set TRACE_THREADINFO to 1 to debug creation/destruction of ThreadInfo
// instances.
#define TRACE_THREADINFO 0
#if TRACE_THREADINFO
#define LOG_THREADINFO(x...) fprintf(stderr, x)
#else
#define LOG_THREADINFO(x...)
#endif
namespace {
class ThreadInfoStore : public ::emugl::ThreadStore {
public:
ThreadInfoStore() : ::emugl::ThreadStore(&destructor) {}
size_t getInstanceCount() const { return mNumInstances; }
private:
static void destructor(void* value) {
LOG_THREADINFO("%s: EFL %p (%d instances)\n", __FUNCTION__,
value, mNumInstances);
delete static_cast<ThreadInfo*>(value);
mNumInstances--;
}
static size_t mNumInstances;
};
size_t ThreadInfoStore::mNumInstances = 0;
} // namespace
void ThreadInfo::updateInfo(ContextPtr eglCtx,
EglDisplay* dpy,
GLEScontext* glesCtx,
ShareGroupPtr share,
ObjectNameManager* manager) {
eglContext = eglCtx;
eglDisplay = dpy;
glesContext = glesCtx;
shareGroup = share;
objManager = manager;
}
static ::emugl::LazyInstance<ThreadInfoStore> s_tls = LAZY_INSTANCE_INIT;
ThreadInfo *getThreadInfo()
{
ThreadInfo *ti = static_cast<ThreadInfo*>(s_tls->get());
if (!ti) {
ti = new ThreadInfo();
s_tls->set(ti);
LOG_THREADINFO("%s: EGL %p (%d instances)\n", __FUNCTION__,
ti, (int)ThreadInfoStore::getInstanceCount());
}
return ti;
}

View file

@ -0,0 +1,42 @@
/*
* 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.
*/
#ifndef THREAD_INFO_H
#define THREAD_INFO_H
#include "EglContext.h"
class EglDisplay;
class GLEScontext;
struct ThreadInfo {
ThreadInfo():eglDisplay(NULL),glesContext(NULL),objManager(NULL){}
void updateInfo(ContextPtr eglctx,
EglDisplay* dpy,
GLEScontext* glesCtx,
ShareGroupPtr share,
ObjectNameManager* manager);
ContextPtr eglContext;
EglDisplay* eglDisplay;
GLEScontext* glesContext;
ShareGroupPtr shareGroup;
ObjectNameManager* objManager;
};
ThreadInfo* getThreadInfo();
#endif

View file

@ -0,0 +1,14 @@
LOCAL_PATH := $(call my-dir)
host_common_SRC_FILES := \
GLEScmImp.cpp \
GLEScmUtils.cpp \
GLEScmContext.cpp \
GLEScmValidate.cpp
### GLES_CM host implementation (On top of OpenGL) ########################
$(call emugl-begin-host-shared-library,lib$(BUILD_TARGET_SUFFIX)GLES_CM_translator)
$(call emugl-import,libGLcommon)
LOCAL_SRC_FILES := $(host_common_SRC_FILES)
$(call emugl-end-module)

View file

@ -0,0 +1,8 @@
set(SOURCES
GLEScmImp.cpp
GLEScmUtils.cpp
GLEScmContext.cpp
GLEScmValidate.cpp)
add_library(GLES_CM_translator SHARED ${SOURCES})
target_link_libraries(GLES_CM_translator GLcommon)

View file

@ -0,0 +1,430 @@
/*
* 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 "GLEScmContext.h"
#include "GLEScmUtils.h"
#include <GLcommon/GLutils.h>
#include <GLcommon/GLconversion_macros.h>
#include <string.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
void GLEScmContext::init(GlLibrary* glLib) {
emugl::Mutex::AutoLock mutex(s_lock);
if(!m_initialized) {
s_glDispatch.dispatchFuncs(GLES_1_1, glLib);
GLEScontext::init(glLib);
m_texCoords = new GLESpointer[s_glSupport.maxTexUnits];
m_map[GL_TEXTURE_COORD_ARRAY] = &m_texCoords[m_clientActiveTexture];
buildStrings((const char*)dispatcher().glGetString(GL_VENDOR),
(const char*)dispatcher().glGetString(GL_RENDERER),
(const char*)dispatcher().glGetString(GL_VERSION),
"OpenGL ES-CM 1.1");
}
m_initialized = true;
}
GLEScmContext::GLEScmContext():GLEScontext(),m_texCoords(NULL),m_pointsIndex(-1), m_clientActiveTexture(0) {
m_map[GL_COLOR_ARRAY] = new GLESpointer();
m_map[GL_NORMAL_ARRAY] = new GLESpointer();
m_map[GL_VERTEX_ARRAY] = new GLESpointer();
m_map[GL_POINT_SIZE_ARRAY_OES] = new GLESpointer();
}
void GLEScmContext::setActiveTexture(GLenum tex) {
m_activeTexture = tex - GL_TEXTURE0;
}
void GLEScmContext::setClientActiveTexture(GLenum tex) {
m_clientActiveTexture = tex - GL_TEXTURE0;
m_map[GL_TEXTURE_COORD_ARRAY] = &m_texCoords[m_clientActiveTexture];
}
GLEScmContext::~GLEScmContext(){
if(m_texCoords){
delete[] m_texCoords;
m_texCoords = NULL;
}
m_map[GL_TEXTURE_COORD_ARRAY] = NULL;
}
//setting client side arr
void GLEScmContext::setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int index){
if( arr == NULL) return;
switch(arrayType) {
case GL_VERTEX_ARRAY:
s_glDispatch.glVertexPointer(size,dataType,stride,arr);
break;
case GL_NORMAL_ARRAY:
s_glDispatch.glNormalPointer(dataType,stride,arr);
break;
case GL_TEXTURE_COORD_ARRAY:
s_glDispatch.glTexCoordPointer(size,dataType,stride,arr);
break;
case GL_COLOR_ARRAY:
s_glDispatch.glColorPointer(size,dataType,stride,arr);
break;
case GL_POINT_SIZE_ARRAY_OES:
m_pointsIndex = index;
break;
}
}
void GLEScmContext::setupArrayPointerHelper(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLenum array_id,GLESpointer* p){
unsigned int size = p->getSize();
GLenum dataType = p->getType();
if(needConvert(cArrs,first,count,type,indices,direct,p,array_id)){
//conversion has occured
ArrayData currentArr = cArrs.getCurrentArray();
setupArr(currentArr.data,array_id,currentArr.type,size,currentArr.stride,GL_FALSE, cArrs.getCurrentIndex());
++cArrs;
} else {
setupArr(p->getData(),array_id,dataType,size,p->getStride(), GL_FALSE);
}
}
void GLEScmContext::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) {
ArraysMap::iterator it;
m_pointsIndex = -1;
//going over all clients arrays Pointers
for ( it=m_map.begin() ; it != m_map.end(); it++ ) {
GLenum array_id = (*it).first;
GLESpointer* p = (*it).second;
if(!isArrEnabled(array_id)) continue;
if(array_id == GL_TEXTURE_COORD_ARRAY) continue; //handling textures later
setupArrayPointerHelper(cArrs,first,count,type,indices,direct,array_id,p);
}
unsigned int activeTexture = m_clientActiveTexture + GL_TEXTURE0;
s_lock.lock();
int maxTexUnits = s_glSupport.maxTexUnits;
s_lock.unlock();
//converting all texture coords arrays
for(int i=0; i< maxTexUnits;i++) {
unsigned int tex = GL_TEXTURE0+i;
setClientActiveTexture(tex);
s_glDispatch.glClientActiveTexture(tex);
GLenum array_id = GL_TEXTURE_COORD_ARRAY;
GLESpointer* p = m_map[array_id];
if(!isArrEnabled(array_id)) continue;
setupArrayPointerHelper(cArrs,first,count,type,indices,direct,array_id,p);
}
setClientActiveTexture(activeTexture);
s_glDispatch.glClientActiveTexture(activeTexture);
}
void GLEScmContext::drawPointsData(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices_in,bool isElemsDraw) {
const char *pointsArr = NULL;
int stride = 0;
GLESpointer* p = m_map[GL_POINT_SIZE_ARRAY_OES];
//choosing the right points sizes array source
if(m_pointsIndex >= 0) { //point size array was converted
pointsArr = (const char*)(cArrs[m_pointsIndex].data);
stride = cArrs[m_pointsIndex].stride;
} else {
pointsArr = static_cast<const char*>(p->getData());
stride = p->getStride();
}
if(stride == 0){
stride = sizeof(GLfloat);
}
if(isElemsDraw) {
int tSize = 0;
switch (type) {
case GL_UNSIGNED_BYTE:
tSize = 1;
break;
case GL_UNSIGNED_SHORT:
tSize = 2;
break;
case GL_UNSIGNED_INT:
tSize = 4;
break;
};
int i = 0;
while(i<count)
{
int sStart = i;
int sCount = 1;
#define INDEX \
(type == GL_UNSIGNED_INT ? \
static_cast<const GLuint*>(indices_in)[i]: \
type == GL_UNSIGNED_SHORT ? \
static_cast<const GLushort*>(indices_in)[i]: \
static_cast<const GLubyte*>(indices_in)[i])
GLfloat pSize = *((GLfloat*)(pointsArr+(INDEX*stride)));
i++;
while(i < count && pSize == *((GLfloat*)(pointsArr+(INDEX*stride))))
{
sCount++;
i++;
}
s_glDispatch.glPointSize(pSize);
s_glDispatch.glDrawElements(GL_POINTS, sCount, type, (char*)indices_in+sStart*tSize);
}
} else {
int i = 0;
while(i<count)
{
int sStart = i;
int sCount = 1;
GLfloat pSize = *((GLfloat*)(pointsArr+((first+i)*stride)));
i++;
while(i < count && pSize == *((GLfloat*)(pointsArr+((first+i)*stride))))
{
sCount++;
i++;
}
s_glDispatch.glPointSize(pSize);
s_glDispatch.glDrawArrays(GL_POINTS, first+sStart, sCount);
}
}
}
void GLEScmContext::drawPointsArrs(GLESConversionArrays& arrs,GLint first,GLsizei count) {
drawPointsData(arrs,first,count,0,NULL,false);
}
void GLEScmContext::drawPointsElems(GLESConversionArrays& arrs,GLsizei count,GLenum type,const GLvoid* indices_in) {
drawPointsData(arrs,0,count,type,indices_in,true);
}
bool GLEScmContext::needConvert(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) {
bool usingVBO = p->isVBO();
GLenum arrType = p->getType();
/*
conversion is not necessary in the following cases:
(*) array type is byte but it is not vertex or texture array
(*) array type is not fixed
*/
if((arrType != GL_FIXED) && (arrType != GL_BYTE)) return false;
if((arrType == GL_BYTE && (array_id != GL_VERTEX_ARRAY)) &&
(arrType == GL_BYTE && (array_id != GL_TEXTURE_COORD_ARRAY)) ) return false;
bool byteVBO = (arrType == GL_BYTE) && usingVBO;
if(byteVBO){
p->redirectPointerData();
}
if(!usingVBO || byteVBO) {
if (direct) {
convertDirect(cArrs,first,count,array_id,p);
} else {
convertIndirect(cArrs,count,type,indices,array_id,p);
}
} else {
if (direct) {
convertDirectVBO(cArrs,first,count,array_id,p) ;
} else {
convertIndirectVBO(cArrs,count,type,indices,array_id,p);
}
}
return true;
}
const GLESpointer* GLEScmContext::getPointer(GLenum arrType) {
GLenum type =
arrType == GL_VERTEX_ARRAY_POINTER ? GL_VERTEX_ARRAY :
arrType == GL_NORMAL_ARRAY_POINTER ? GL_NORMAL_ARRAY :
arrType == GL_TEXTURE_COORD_ARRAY_POINTER ? GL_TEXTURE_COORD_ARRAY :
arrType == GL_COLOR_ARRAY_POINTER ? GL_COLOR_ARRAY :
arrType == GL_POINT_SIZE_ARRAY_POINTER_OES ? GL_POINT_SIZE_ARRAY_OES :
0;
if(type != 0)
{
return GLEScontext::getPointer(type);
}
return NULL;
}
void GLEScmContext::initExtensionString() {
*s_glExtensions = "GL_OES_blend_func_separate GL_OES_blend_equation_separate GL_OES_blend_subtract "
"GL_OES_byte_coordinates GL_OES_compressed_paletted_texture GL_OES_point_size_array "
"GL_OES_point_sprite GL_OES_single_precision GL_OES_stencil_wrap GL_OES_texture_env_crossbar "
"GL_OES_texture_mirored_repeat GL_OES_EGL_image GL_OES_element_index_uint GL_OES_draw_texture "
"GL_OES_texture_cube_map GL_OES_draw_texture ";
if (s_glSupport.GL_OES_READ_FORMAT)
*s_glExtensions+="GL_OES_read_format ";
if (s_glSupport.GL_EXT_FRAMEBUFFER_OBJECT) {
*s_glExtensions+="GL_OES_framebuffer_object GL_OES_depth24 GL_OES_depth32 GL_OES_fbo_render_mipmap "
"GL_OES_rgb8_rgba8 GL_OES_stencil1 GL_OES_stencil4 GL_OES_stencil8 ";
}
if (s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL)
*s_glExtensions+="GL_OES_packed_depth_stencil ";
if (s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888)
*s_glExtensions+="GL_EXT_texture_format_BGRA8888 GL_APPLE_texture_format_BGRA8888 ";
if (s_glSupport.GL_ARB_MATRIX_PALETTE && s_glSupport.GL_ARB_VERTEX_BLEND) {
*s_glExtensions+="GL_OES_matrix_palette ";
GLint max_palette_matrices=0;
GLint max_vertex_units=0;
dispatcher().glGetIntegerv(GL_MAX_PALETTE_MATRICES_OES,&max_palette_matrices);
dispatcher().glGetIntegerv(GL_MAX_VERTEX_UNITS_OES,&max_vertex_units);
if (max_palette_matrices>=32 && max_vertex_units>=4)
*s_glExtensions+="GL_OES_extended_matrix_palette ";
}
*s_glExtensions+="GL_OES_compressed_ETC1_RGB8_texture ";
}
int GLEScmContext::getMaxTexUnits() {
return getCaps()->maxTexUnits;
}
bool GLEScmContext::glGetBooleanv(GLenum pname, GLboolean *params)
{
GLint iParam;
if(glGetIntegerv(pname, &iParam))
{
*params = (iParam != 0);
return true;
}
return false;
}
bool GLEScmContext::glGetFixedv(GLenum pname, GLfixed *params)
{
GLint iParam;
if(glGetIntegerv(pname, &iParam))
{
*params = I2X(iParam);
return true;
}
return false;
}
bool GLEScmContext::glGetFloatv(GLenum pname, GLfloat *params)
{
GLint iParam;
if(glGetIntegerv(pname, &iParam))
{
*params = (GLfloat)iParam;
return true;
}
return false;
}
bool GLEScmContext::glGetIntegerv(GLenum pname, GLint *params)
{
if(GLEScontext::glGetIntegerv(pname, params))
return true;
const GLESpointer* ptr = NULL;
switch(pname){
case GL_VERTEX_ARRAY_BUFFER_BINDING:
case GL_VERTEX_ARRAY_SIZE:
case GL_VERTEX_ARRAY_STRIDE:
case GL_VERTEX_ARRAY_TYPE:
ptr = getPointer(GL_VERTEX_ARRAY_POINTER);
break;
case GL_NORMAL_ARRAY_BUFFER_BINDING:
case GL_NORMAL_ARRAY_STRIDE:
case GL_NORMAL_ARRAY_TYPE:
ptr = getPointer(GL_NORMAL_ARRAY_POINTER);
break;
case GL_COLOR_ARRAY_BUFFER_BINDING:
case GL_COLOR_ARRAY_SIZE:
case GL_COLOR_ARRAY_STRIDE:
case GL_COLOR_ARRAY_TYPE:
ptr = getPointer(GL_COLOR_ARRAY_POINTER);
break;
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
case GL_TEXTURE_COORD_ARRAY_SIZE:
case GL_TEXTURE_COORD_ARRAY_STRIDE:
case GL_TEXTURE_COORD_ARRAY_TYPE:
ptr = getPointer(GL_TEXTURE_COORD_ARRAY_POINTER);
break;
case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
case GL_POINT_SIZE_ARRAY_STRIDE_OES:
case GL_POINT_SIZE_ARRAY_TYPE_OES:
ptr = getPointer(GL_POINT_SIZE_ARRAY_POINTER_OES);
break;
default:
return false;
}
switch(pname)
{
case GL_VERTEX_ARRAY_BUFFER_BINDING:
case GL_NORMAL_ARRAY_BUFFER_BINDING:
case GL_COLOR_ARRAY_BUFFER_BINDING:
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
*params = ptr ? ptr->getBufferName() : 0;
break;
case GL_VERTEX_ARRAY_STRIDE:
case GL_NORMAL_ARRAY_STRIDE:
case GL_COLOR_ARRAY_STRIDE:
case GL_TEXTURE_COORD_ARRAY_STRIDE:
case GL_POINT_SIZE_ARRAY_STRIDE_OES:
*params = ptr ? ptr->getStride() : 0;
break;
case GL_VERTEX_ARRAY_SIZE:
case GL_COLOR_ARRAY_SIZE:
case GL_TEXTURE_COORD_ARRAY_SIZE:
*params = ptr ? ptr->getSize() : 0;
break;
case GL_VERTEX_ARRAY_TYPE:
case GL_NORMAL_ARRAY_TYPE:
case GL_COLOR_ARRAY_TYPE:
case GL_TEXTURE_COORD_ARRAY_TYPE:
case GL_POINT_SIZE_ARRAY_TYPE_OES:
*params = ptr ? ptr->getType() : 0;
break;
}
return true;
}

View file

@ -0,0 +1,71 @@
/*
* 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.
*/
#ifndef GLES_CM_CONTEX_H
#define GLES_CM_CONTEX_H
#include <GLcommon/GLDispatch.h>
#include <GLcommon/GLESpointer.h>
#include <GLcommon/GLESbuffer.h>
#include <GLcommon/GLEScontext.h>
#include <map>
#include <vector>
#include <string>
typedef std::map<GLfloat,std::vector<int> > PointSizeIndices;
class GlLibrary;
class GLEScmContext: public GLEScontext
{
public:
virtual void init(GlLibrary* glLib);
GLEScmContext();
void setActiveTexture(GLenum tex);
void setClientActiveTexture(GLenum tex);
GLenum getActiveTexture() { return GL_TEXTURE0 + m_activeTexture;};
GLenum getClientActiveTexture() { return GL_TEXTURE0 + m_clientActiveTexture;};
void setupArraysPointers(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct);
void drawPointsArrs(GLESConversionArrays& arrs,GLint first,GLsizei count);
void drawPointsElems(GLESConversionArrays& arrs,GLsizei count,GLenum type,const GLvoid* indices);
virtual const GLESpointer* getPointer(GLenum arrType);
int getMaxTexUnits();
virtual bool glGetIntegerv(GLenum pname, GLint *params);
virtual bool glGetBooleanv(GLenum pname, GLboolean *params);
virtual bool glGetFloatv(GLenum pname, GLfloat *params);
virtual bool glGetFixedv(GLenum pname, GLfixed *params);
~GLEScmContext();
protected:
bool needConvert(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id);
private:
void setupArrayPointerHelper(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLenum array_id,GLESpointer* p);
void setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int pointsIndex = -1);
void drawPoints(PointSizeIndices* points);
void drawPointsData(GLESConversionArrays& arrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices_in,bool isElemsDraw);
void initExtensionString();
GLESpointer* m_texCoords;
int m_pointsIndex;
unsigned int m_clientActiveTexture;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,101 @@
/*
* 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 "GLEScmUtils.h"
size_t glParamSize(GLenum param)
{
size_t s = 0;
switch(param)
{
case GL_MAX_TEXTURE_SIZE:
//case GL_TEXTURE_GEN_MODE_OES:
case GL_TEXTURE_ENV_MODE:
case GL_FOG_MODE:
case GL_FOG_DENSITY:
case GL_FOG_START:
case GL_FOG_END:
case GL_SPOT_EXPONENT:
case GL_CONSTANT_ATTENUATION:
case GL_LINEAR_ATTENUATION:
case GL_QUADRATIC_ATTENUATION:
case GL_SHININESS:
case GL_LIGHT_MODEL_TWO_SIDE:
case GL_POINT_SIZE:
case GL_POINT_SIZE_MIN:
case GL_POINT_SIZE_MAX:
case GL_POINT_FADE_THRESHOLD_SIZE:
case GL_CULL_FACE_MODE:
case GL_FRONT_FACE:
case GL_SHADE_MODEL:
case GL_DEPTH_WRITEMASK:
case GL_DEPTH_CLEAR_VALUE:
case GL_STENCIL_FAIL:
case GL_STENCIL_PASS_DEPTH_FAIL:
case GL_STENCIL_PASS_DEPTH_PASS:
case GL_STENCIL_REF:
case GL_STENCIL_WRITEMASK:
case GL_MATRIX_MODE:
case GL_MODELVIEW_STACK_DEPTH:
case GL_PROJECTION_STACK_DEPTH:
case GL_TEXTURE_STACK_DEPTH:
case GL_ALPHA_TEST_FUNC:
case GL_ALPHA_TEST_REF:
case GL_BLEND_DST:
case GL_BLEND_SRC:
case GL_LOGIC_OP_MODE:
case GL_SCISSOR_TEST:
case GL_MAX_TEXTURE_UNITS:
s = 1;
break;
case GL_ALIASED_LINE_WIDTH_RANGE:
case GL_ALIASED_POINT_SIZE_RANGE:
case GL_DEPTH_RANGE:
case GL_MAX_VIEWPORT_DIMS:
case GL_SMOOTH_POINT_SIZE_RANGE:
case GL_SMOOTH_LINE_WIDTH_RANGE:
s= 2;
break;
case GL_SPOT_DIRECTION:
case GL_POINT_DISTANCE_ATTENUATION:
case GL_CURRENT_NORMAL:
s = 3;
break;
case GL_CURRENT_TEXTURE_COORDS:
case GL_CURRENT_COLOR:
case GL_FOG_COLOR:
case GL_AMBIENT:
case GL_DIFFUSE:
case GL_SPECULAR:
case GL_EMISSION:
case GL_POSITION:
case GL_LIGHT_MODEL_AMBIENT:
case GL_TEXTURE_ENV_COLOR:
case GL_SCISSOR_BOX:
case GL_VIEWPORT:
//case GL_TEXTURE_CROP_RECT_OES:
s = 4;
break;
case GL_MODELVIEW_MATRIX:
case GL_PROJECTION_MATRIX:
case GL_TEXTURE_MATRIX:
s = 16;
default:
s = 1; // assume 1
}
return s;
}

View file

@ -0,0 +1,22 @@
/*
* 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.
*/
#ifndef GLES_UTILS_H
#define GLES_UTILS_H
#include <GLES/gl.h>
#include <stdlib.h>
size_t glParamSize(GLenum param);
#endif

View file

@ -0,0 +1,306 @@
/*
* 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 "GLEScmValidate.h"
#include <GLcommon/GLutils.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <GLcommon/GLEScontext.h>
#include "GLEScmValidate.h"
bool GLEScmValidate::lightEnum(GLenum e,unsigned int maxLights) {
return e >=GL_LIGHT0 && e <= (GL_LIGHT0+maxLights);
}
bool GLEScmValidate::clipPlaneEnum(GLenum e,unsigned int maxClipPlanes) {
return e >=GL_CLIP_PLANE0 && e <= (GL_CLIP_PLANE0+maxClipPlanes);
}
bool GLEScmValidate::alphaFunc(GLenum f) {
switch(f) {
case GL_NEVER:
case GL_LESS:
case GL_EQUAL:
case GL_LEQUAL:
case GL_GREATER:
case GL_NOTEQUAL:
case GL_GEQUAL:
case GL_ALWAYS:
return true;
}
return false;
}
bool GLEScmValidate::blendSrc(GLenum s) {
switch(s) {
case GL_ZERO:
case GL_ONE:
case GL_DST_COLOR:
case GL_ONE_MINUS_DST_COLOR:
case GL_SRC_ALPHA:
case GL_ONE_MINUS_SRC_ALPHA:
case GL_DST_ALPHA:
case GL_ONE_MINUS_DST_ALPHA:
case GL_SRC_ALPHA_SATURATE:
return true;
}
return false;
}
bool GLEScmValidate::vertexPointerParams(GLint size,GLsizei stride) {
return ((size >=2) && (size <= 4)) && (stride >=0) ;
}
bool GLEScmValidate::colorPointerParams(GLint size,GLsizei stride) {
return (size == 4) && (stride >=0) ;
}
bool GLEScmValidate::texCoordPointerParams(GLint size,GLsizei stride) {
return ((size >=2) && (size <= 4)) && (stride >=0) ;
}
bool GLEScmValidate::supportedArrays(GLenum arr) {
switch(arr) {
case GL_COLOR_ARRAY:
case GL_NORMAL_ARRAY:
case GL_POINT_SIZE_ARRAY_OES:
case GL_TEXTURE_COORD_ARRAY:
case GL_VERTEX_ARRAY:
return true;
}
return false;
}
bool GLEScmValidate::hintTargetMode(GLenum target,GLenum mode) {
switch(target) {
case GL_FOG_HINT:
case GL_GENERATE_MIPMAP_HINT:
case GL_LINE_SMOOTH_HINT:
case GL_PERSPECTIVE_CORRECTION_HINT:
case GL_POINT_SMOOTH_HINT:
break;
default: return false;
}
switch(mode) {
case GL_FASTEST:
case GL_NICEST:
case GL_DONT_CARE:
break;
default: return false;
}
return true;
}
bool GLEScmValidate::texParams(GLenum target,GLenum pname) {
switch(pname) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_CROP_RECT_OES:
case GL_GENERATE_MIPMAP:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
break;
default:
return false;
}
return (target == GL_TEXTURE_2D)||(target == GL_TEXTURE_CUBE_MAP_OES);
}
bool GLEScmValidate::texEnv(GLenum target,GLenum pname) {
switch(pname) {
case GL_TEXTURE_ENV_MODE:
case GL_TEXTURE_ENV_COLOR:
case GL_COMBINE_RGB:
case GL_COMBINE_ALPHA:
case GL_SRC0_RGB:
case GL_SRC1_RGB:
case GL_SRC2_RGB:
case GL_SRC0_ALPHA:
case GL_SRC1_ALPHA:
case GL_SRC2_ALPHA:
case GL_OPERAND0_RGB:
case GL_OPERAND1_RGB:
case GL_OPERAND2_RGB:
case GL_OPERAND0_ALPHA:
case GL_OPERAND1_ALPHA:
case GL_OPERAND2_ALPHA:
case GL_RGB_SCALE:
case GL_ALPHA_SCALE:
case GL_COORD_REPLACE_OES:
break;
default:
return false;
}
return (target == GL_TEXTURE_ENV || target == GL_POINT_SPRITE_OES);
}
bool GLEScmValidate::capability(GLenum cap,int maxLights,int maxClipPlanes) {
switch(cap) {
case GL_ALPHA_TEST:
case GL_BLEND:
case GL_COLOR_ARRAY:
case GL_COLOR_LOGIC_OP:
case GL_COLOR_MATERIAL:
case GL_CULL_FACE:
case GL_DEPTH_TEST:
case GL_DITHER:
case GL_FOG:
case GL_LIGHTING:
case GL_LINE_SMOOTH:
case GL_MULTISAMPLE:
case GL_NORMAL_ARRAY:
case GL_NORMALIZE:
case GL_POINT_SIZE_ARRAY_OES:
case GL_POINT_SMOOTH:
case GL_POINT_SPRITE_OES:
case GL_POLYGON_OFFSET_FILL:
case GL_RESCALE_NORMAL:
case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_ALPHA_TO_ONE:
case GL_SAMPLE_COVERAGE:
case GL_SCISSOR_TEST:
case GL_STENCIL_TEST:
case GL_TEXTURE_2D:
case GL_TEXTURE_COORD_ARRAY:
case GL_VERTEX_ARRAY:
return true;
}
return GLEScmValidate::lightEnum(cap,maxLights) || GLEScmValidate::clipPlaneEnum(cap,maxClipPlanes);
}
bool GLEScmValidate::texCompImgFrmt(GLenum format) {
switch(format) {
case GL_PALETTE4_RGB8_OES:
case GL_PALETTE4_RGBA8_OES:
case GL_PALETTE4_R5_G6_B5_OES:
case GL_PALETTE4_RGBA4_OES:
case GL_PALETTE4_RGB5_A1_OES:
case GL_PALETTE8_RGB8_OES:
case GL_PALETTE8_RGBA8_OES:
case GL_PALETTE8_R5_G6_B5_OES:
case GL_PALETTE8_RGBA4_OES:
case GL_PALETTE8_RGB5_A1_OES:
return true;
}
return false;
}
bool GLEScmValidate::blendDst(GLenum d) {
switch(d) {
case GL_ZERO:
case GL_ONE:
case GL_SRC_COLOR:
case GL_ONE_MINUS_SRC_COLOR:
case GL_SRC_ALPHA:
case GL_ONE_MINUS_SRC_ALPHA:
case GL_DST_ALPHA:
case GL_ONE_MINUS_DST_ALPHA:
return true;
}
return false;
}
bool GLEScmValidate::renderbufferInternalFrmt(GLEScontext* ctx, GLenum internalformat)
{
switch (internalformat) {
case GL_DEPTH_COMPONENT16_OES:
case GL_RGBA4_OES:
case GL_RGB5_A1_OES:
case GL_RGB565_OES:
case GL_STENCIL_INDEX1_OES:
case GL_STENCIL_INDEX4_OES:
case GL_STENCIL_INDEX8_OES:
case GL_RGB8_OES:
case GL_RGBA8_OES:
case GL_DEPTH_COMPONENT24_OES:
case GL_DEPTH_COMPONENT32_OES:
return true;
}
if (ctx->getCaps()->GL_EXT_PACKED_DEPTH_STENCIL && internalformat==GL_DEPTH24_STENCIL8_OES)
return true;
return false;
}
bool GLEScmValidate::stencilOp(GLenum param) {
switch (param) {
case GL_KEEP:
case GL_ZERO:
case GL_REPLACE:
case GL_INCR:
case GL_DECR:
case GL_INVERT:
case GL_INCR_WRAP_OES:
case GL_DECR_WRAP_OES:
return true;
}
return false;
}
bool GLEScmValidate::texGen(GLenum coord, GLenum pname) {
return (coord == GL_TEXTURE_GEN_STR_OES && pname == GL_TEXTURE_GEN_MODE_OES);
}
bool GLEScmValidate::colorPointerType(GLenum type){
switch(type){
case GL_UNSIGNED_BYTE:
case GL_FIXED:
case GL_FLOAT:
return true;
}
return false;
}
bool GLEScmValidate::normalPointerType(GLenum type){
switch(type){
case GL_BYTE:
case GL_SHORT:
case GL_FLOAT:
case GL_FIXED:
return true;
}
return false;
}
bool GLEScmValidate::pointPointerType(GLenum type){
return type == GL_FIXED || type == GL_FLOAT;
}
bool GLEScmValidate::texCoordPointerType(GLenum type){
switch(type){
case GL_BYTE:
case GL_SHORT:
case GL_FLOAT:
case GL_FIXED:
return true;
}
return false;
}
bool GLEScmValidate::vertexPointerType(GLenum type){
switch(type){
case GL_BYTE:
case GL_SHORT:
case GL_FLOAT:
case GL_FIXED:
return true;
}
return false;
}

View file

@ -0,0 +1,50 @@
/*
* 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.
*/
#ifndef GLES_CM_VALIDATE_H
#define GLES_CM_VALIDATE_H
#include <GLES/gl.h>
#include <GLcommon/GLESvalidate.h>
struct GLEScmValidate : public GLESvalidate
{
static bool blendSrc(GLenum s);
static bool blendDst(GLenum d);
static bool lightEnum(GLenum e,unsigned int maxLIghts);
static bool clipPlaneEnum(GLenum e,unsigned int maxClipPlanes);
static bool alphaFunc(GLenum f);
static bool vertexPointerParams(GLint size,GLsizei stride);
static bool colorPointerParams(GLint size,GLsizei stride);
static bool supportedArrays(GLenum arr);
static bool hintTargetMode(GLenum target,GLenum mode);
static bool capability(GLenum cap,int maxLights,int maxClipPlanes);
static bool texParams(GLenum target,GLenum pname);
static bool texCoordPointerParams(GLint size,GLsizei stride);
static bool texEnv(GLenum target,GLenum pname);
static bool texCompImgFrmt(GLenum format);
static bool renderbufferInternalFrmt(GLEScontext * ctx, GLenum internalformat);
static bool stencilOp(GLenum param);
static bool texGen(GLenum coord,GLenum pname);
static bool colorPointerType(GLenum type);
static bool normalPointerType(GLenum type);
static bool pointPointerType(GLenum type);
static bool texCoordPointerType(GLenum type);
static bool vertexPointerType(GLenum type);
};
#endif

View file

@ -0,0 +1,17 @@
LOCAL_PATH := $(call my-dir)
host_common_SRC_FILES := \
GLESv2Imp.cpp \
GLESv2Context.cpp \
GLESv2Validate.cpp \
ShaderParser.cpp \
ProgramData.cpp
### GLES_V2 host implementation (On top of OpenGL) ########################
$(call emugl-begin-host-shared-library,lib$(BUILD_TARGET_SUFFIX)GLES_V2_translator)
$(call emugl-import, libGLcommon)
LOCAL_SRC_FILES := $(host_common_SRC_FILES)
$(call emugl-end-module)

View file

@ -0,0 +1,9 @@
set(SOURCES
GLESv2Imp.cpp
GLESv2Context.cpp
GLESv2Validate.cpp
ShaderParser.cpp
ProgramData.cpp)
add_library(GLES_V2_translator SHARED ${SOURCES})
target_link_libraries(GLES_V2_translator GLcommon)

View file

@ -0,0 +1,175 @@
/*
* 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 "GLESv2Context.h"
#include <string.h>
void GLESv2Context::init(GlLibrary* glLib) {
emugl::Mutex::AutoLock mutex(s_lock);
if(!m_initialized) {
s_glDispatch.dispatchFuncs(GLES_2_0, glLib);
GLEScontext::init(glLib);
for(int i=0; i < s_glSupport.maxVertexAttribs;i++){
m_map[i] = new GLESpointer();
}
setAttribute0value(0.0, 0.0, 0.0, 1.0);
buildStrings((const char*)dispatcher().glGetString(GL_VENDOR),
(const char*)dispatcher().glGetString(GL_RENDERER),
(const char*)dispatcher().glGetString(GL_VERSION),
"OpenGL ES 2.0");
}
m_initialized = true;
}
GLESv2Context::GLESv2Context():GLEScontext(), m_att0Array(NULL), m_att0ArrayLength(0), m_att0NeedsDisable(false){};
GLESv2Context::~GLESv2Context()
{
delete[] m_att0Array;
}
void GLESv2Context::setAttribute0value(float x, float y, float z, float w)
{
m_attribute0value[0] = x;
m_attribute0value[1] = y;
m_attribute0value[2] = z;
m_attribute0value[3] = w;
}
void GLESv2Context::validateAtt0PreDraw(unsigned int count)
{
m_att0NeedsDisable = false;
if(count == 0)
return;
int enabled = 0;
s_glDispatch.glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
if(enabled)
return;
if(count > m_att0ArrayLength)
{
delete [] m_att0Array;
m_att0Array = new GLfloat[4*count];
m_att0ArrayLength = count;
}
for(unsigned int i=0; i<count; i++)
memcpy(m_att0Array+i*4, m_attribute0value, 4*sizeof(GLfloat));
s_glDispatch.glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, m_att0Array);
s_glDispatch.glEnableVertexAttribArray(0);
m_att0NeedsDisable = true;
}
void GLESv2Context::validateAtt0PostDraw(void)
{
if(m_att0NeedsDisable)
s_glDispatch.glDisableVertexAttribArray(0);
m_att0NeedsDisable = false;
}
void GLESv2Context::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) {
ArraysMap::iterator it;
//going over all clients arrays Pointers
for ( it=m_map.begin() ; it != m_map.end(); it++ ) {
GLenum array_id = (*it).first;
GLESpointer* p = (*it).second;
if(!isArrEnabled(array_id)) continue;
unsigned int size = p->getSize();
if(needConvert(cArrs,first,count,type,indices,direct,p,array_id)){
//conversion has occured
ArrayData currentArr = cArrs.getCurrentArray();
setupArr(currentArr.data,array_id,currentArr.type,size,currentArr.stride, p->getNormalized());
++cArrs;
} else {
setupArr(p->getData(),array_id,p->getType(),
size,p->getStride(), p->getNormalized());
}
}
}
//setting client side arr
void GLESv2Context::setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int index){
if(arr == NULL) return;
s_glDispatch.glVertexAttribPointer(arrayType,size,dataType,normalized,stride,arr);
}
bool GLESv2Context::needConvert(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) {
bool usingVBO = p->isVBO();
GLenum arrType = p->getType();
/*
conversion is not necessary in the following cases:
(*) array type is not fixed
*/
if(arrType != GL_FIXED) return false;
if(!usingVBO) {
if (direct) {
convertDirect(cArrs,first,count,array_id,p);
} else {
convertIndirect(cArrs,count,type,indices,array_id,p);
}
} else {
if (direct) {
convertDirectVBO(cArrs,first,count,array_id,p) ;
} else {
convertIndirectVBO(cArrs,count,type,indices,array_id,p);
}
}
return true;
}
void GLESv2Context::initExtensionString() {
*s_glExtensions = "GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_depth24 GL_OES_depth32 GL_OES_element_index_uint "
"GL_OES_texture_float GL_OES_texture_float_linear "
"GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth_texture ";
if (s_glSupport.GL_ARB_HALF_FLOAT_PIXEL || s_glSupport.GL_NV_HALF_FLOAT)
*s_glExtensions+="GL_OES_texture_half_float GL_OES_texture_half_float_linear ";
if (s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL)
*s_glExtensions+="GL_OES_packed_depth_stencil ";
if (s_glSupport.GL_ARB_HALF_FLOAT_VERTEX)
*s_glExtensions+="GL_OES_vertex_half_float ";
if (s_glSupport.GL_OES_STANDARD_DERIVATIVES)
*s_glExtensions+="GL_OES_standard_derivatives ";
if (s_glSupport.GL_OES_TEXTURE_NPOT)
*s_glExtensions+="GL_OES_texture_npot ";
if (s_glSupport.GL_OES_RGB8_RGBA8) {
*s_glExtensions+="GL_OES_rgb8_rgba8 ";
}
}
int GLESv2Context::getMaxTexUnits() {
return getCaps()->maxTexImageUnits;
}
int GLESv2Context::getMaxCombinedTexUnits() {
// GLES spec requires only 2, and the ATI driver erronously
// returns 32 (although it supports only 16). This WAR is simple,
// compliant and good enough for developers.
if (getCaps()->maxCombinedTexImageUnits > 16)
return 16;
return getCaps()->maxCombinedTexImageUnits;
}

View file

@ -0,0 +1,54 @@
/*
* Copyright 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.
*/
#ifndef GLES_V2_CONTEXT_H
#define GLES_V2_CONTEXT_H
#include <GLcommon/GLDispatch.h>
#include <GLcommon/GLEScontext.h>
#include <GLcommon/objectNameManager.h>
class GLESv2Context : public GLEScontext{
public:
virtual void init(GlLibrary* glLib);
GLESv2Context();
virtual ~GLESv2Context();
void setupArraysPointers(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct);
int getMaxCombinedTexUnits();
int getMaxTexUnits();
// This whole att0 thing is about a incompatibility between GLES and OpenGL.
// GLES allows a vertex shader attribute to be in location 0 and have a
// current value, while OpenGL is not very clear about this, which results
// in each implementation doing something different.
void setAttribute0value(float x, float y, float z, float w);
void validateAtt0PreDraw(unsigned int count);
void validateAtt0PostDraw(void);
const float* getAtt0(void) {return m_attribute0value;}
protected:
bool needConvert(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id);
private:
void setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int pointsIndex = -1);
void initExtensionString();
float m_attribute0value[4];
GLfloat* m_att0Array;
unsigned int m_att0ArrayLength;
bool m_att0NeedsDisable;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,198 @@
/*
* 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 "GLESv2Validate.h"
#include <string.h>
bool GLESv2Validate::blendEquationMode(GLenum mode){
return mode == GL_FUNC_ADD ||
mode == GL_FUNC_SUBTRACT ||
mode == GL_FUNC_REVERSE_SUBTRACT;
}
bool GLESv2Validate::blendSrc(GLenum s) {
switch(s) {
case GL_ZERO:
case GL_ONE:
case GL_SRC_COLOR:
case GL_ONE_MINUS_SRC_COLOR:
case GL_DST_COLOR:
case GL_ONE_MINUS_DST_COLOR:
case GL_SRC_ALPHA:
case GL_ONE_MINUS_SRC_ALPHA:
case GL_DST_ALPHA:
case GL_ONE_MINUS_DST_ALPHA:
case GL_CONSTANT_COLOR:
case GL_ONE_MINUS_CONSTANT_COLOR:
case GL_CONSTANT_ALPHA:
case GL_ONE_MINUS_CONSTANT_ALPHA:
case GL_SRC_ALPHA_SATURATE:
return true;
}
return false;
}
bool GLESv2Validate::blendDst(GLenum d) {
switch(d) {
case GL_ZERO:
case GL_ONE:
case GL_SRC_COLOR:
case GL_ONE_MINUS_SRC_COLOR:
case GL_DST_COLOR:
case GL_ONE_MINUS_DST_COLOR:
case GL_SRC_ALPHA:
case GL_ONE_MINUS_SRC_ALPHA:
case GL_DST_ALPHA:
case GL_ONE_MINUS_DST_ALPHA:
case GL_CONSTANT_COLOR:
case GL_ONE_MINUS_CONSTANT_COLOR:
case GL_CONSTANT_ALPHA:
case GL_ONE_MINUS_CONSTANT_ALPHA:
return true;
}
return false;
}
bool GLESv2Validate::textureParams(GLenum param){
switch(param) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
return true;
default:
return false;
}
}
bool GLESv2Validate::hintTargetMode(GLenum target,GLenum mode){
switch(mode) {
case GL_FASTEST:
case GL_NICEST:
case GL_DONT_CARE:
break;
default: return false;
}
return target == GL_GENERATE_MIPMAP_HINT || target == GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES;
}
bool GLESv2Validate::capability(GLenum cap){
switch(cap){
case GL_BLEND:
case GL_CULL_FACE:
case GL_DEPTH_TEST:
case GL_DITHER:
case GL_POLYGON_OFFSET_FILL:
case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_COVERAGE:
case GL_SCISSOR_TEST:
case GL_STENCIL_TEST:
return true;
}
return false;
}
bool GLESv2Validate::pixelStoreParam(GLenum param){
return param == GL_PACK_ALIGNMENT || param == GL_UNPACK_ALIGNMENT;
}
bool GLESv2Validate::readPixelFrmt(GLenum format){
switch(format) {
case GL_ALPHA:
case GL_LUMINANCE_ALPHA:
case GL_RGB:
case GL_RGBA:
return true;
}
return false;
}
bool GLESv2Validate::shaderType(GLenum type){
return type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER;
}
bool GLESv2Validate::precisionType(GLenum type){
switch(type){
case GL_LOW_FLOAT:
case GL_MEDIUM_FLOAT:
case GL_HIGH_FLOAT:
case GL_LOW_INT:
case GL_MEDIUM_INT:
case GL_HIGH_INT:
return true;
}
return false;
}
bool GLESv2Validate::arrayIndex(GLEScontext * ctx,GLuint index) {
return index < (GLuint)ctx->getCaps()->maxVertexAttribs;
}
bool GLESv2Validate::pixelType(GLEScontext * ctx,GLenum type) {
if(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT)
return true;
return GLESvalidate::pixelType(ctx, type);
}
bool GLESv2Validate::pixelFrmt(GLEScontext* ctx,GLenum format) {
if(format == GL_DEPTH_COMPONENT)
return true;
return GLESvalidate::pixelFrmt(ctx, format);
}
bool GLESv2Validate::attribName(const GLchar* name){
const GLchar* found = strstr(name,"gl_");
return (!found) ||
(found != name) ; // attrib name does not start with gl_
}
bool GLESv2Validate::attribIndex(int index){
return index >=0 && index < GL_MAX_VERTEX_ATTRIBS;
}
bool GLESv2Validate::programParam(GLenum pname){
switch(pname){
case GL_DELETE_STATUS:
case GL_LINK_STATUS:
case GL_VALIDATE_STATUS:
case GL_INFO_LOG_LENGTH:
case GL_ATTACHED_SHADERS:
case GL_ACTIVE_ATTRIBUTES:
case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
case GL_ACTIVE_UNIFORMS:
case GL_ACTIVE_UNIFORM_MAX_LENGTH:
return true;
}
return false;
}
bool GLESv2Validate::textureIsCubeMap(GLenum target){
switch(target){
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
return true;
}
return false;
}

View file

@ -0,0 +1,44 @@
/*
* Copyright 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.
*/
#ifndef GLES_V2_VALIDATE_H
#define GLES_V2_VALIDATE_H
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLcommon/GLESvalidate.h>
struct GLESv2Validate:public GLESvalidate{
static bool blendEquationMode(GLenum mode);
static bool blendSrc(GLenum s);
static bool blendDst(GLenum d);
static bool textureParams(GLenum param);
static bool hintTargetMode(GLenum target,GLenum mode);
static bool capability(GLenum cap);
static bool pixelStoreParam(GLenum param);
static bool readPixelFrmt(GLenum format);
static bool shaderType(GLenum type);
static bool precisionType(GLenum type);
static bool arrayIndex(GLEScontext * ctx,GLuint index);
static bool pixelType(GLEScontext * ctx,GLenum type);
static bool pixelFrmt(GLEScontext* ctx,GLenum format);
static bool attribName(const GLchar* name);
static bool attribIndex(int index);
static bool programParam(GLenum pname);
static bool textureIsCubeMap(GLenum target);
};
#endif

View file

@ -0,0 +1,98 @@
/*
* 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 <GLES2/gl2.h>
#include <GLcommon/objectNameManager.h>
#include "ProgramData.h"
ProgramData::ProgramData() : ObjectData(PROGRAM_DATA),
AttachedVertexShader(0),
AttachedFragmentShader(0),
LinkStatus(GL_FALSE),
IsInUse(false),
DeleteStatus(false) {
infoLog = new GLchar[1];
infoLog[0] = '\0';
}
ProgramData::~ProgramData () {
delete[] infoLog;
};
void ProgramData::setInfoLog(GLchar* log) {
delete[] infoLog;
infoLog = log;
}
GLchar* ProgramData::getInfoLog() {
return infoLog;
}
GLuint ProgramData::getAttachedVertexShader() {
return AttachedVertexShader;
}
GLuint ProgramData::getAttachedFragmentShader() {
return AttachedFragmentShader;
}
GLuint ProgramData::getAttachedShader(GLenum type) {
GLuint shader = 0;
switch (type) {
case GL_VERTEX_SHADER:
shader = AttachedVertexShader;
break;
case GL_FRAGMENT_SHADER:
shader = AttachedFragmentShader;
break;
}
return shader;
}
bool ProgramData::attachShader(GLuint shader,GLenum type) {
if (type==GL_VERTEX_SHADER && AttachedVertexShader==0) {
AttachedVertexShader=shader;
return true;
}
else if (type==GL_FRAGMENT_SHADER && AttachedFragmentShader==0) {
AttachedFragmentShader=shader;
return true;
}
return false;
}
bool ProgramData::isAttached(GLuint shader) {
return (AttachedFragmentShader==shader || AttachedVertexShader==shader);
}
bool ProgramData::detachShader(GLuint shader) {
if (AttachedVertexShader==shader) {
AttachedVertexShader = 0;
return true;
}
else if (AttachedFragmentShader==shader) {
AttachedFragmentShader = 0;
return true;
}
return false;
}
void ProgramData::setLinkStatus(GLint status) {
LinkStatus = status;
}
GLint ProgramData::getLinkStatus() {
return LinkStatus;
}

View file

@ -0,0 +1,51 @@
/*
* 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.
*/
#ifndef PROGRAM_DATA_H
#define PROGRAM_DATA_H
class ProgramData:public ObjectData{
public:
ProgramData();
virtual ~ProgramData();
GLuint getAttachedVertexShader();
GLuint getAttachedFragmentShader();
GLuint getAttachedShader(GLenum type);
bool attachShader(GLuint shader,GLenum type);
bool isAttached(GLuint shader);
bool detachShader(GLuint shader);
void setLinkStatus(GLint status);
GLint getLinkStatus();
void setInfoLog(GLchar *log);
GLchar* getInfoLog();
bool isInUse() const { return IsInUse; }
void setInUse(bool inUse) { IsInUse = inUse; }
bool getDeleteStatus() const { return DeleteStatus; }
void setDeleteStatus(bool status) { DeleteStatus = status; }
private:
GLuint AttachedVertexShader;
GLuint AttachedFragmentShader;
GLint LinkStatus;
GLchar* infoLog;
bool IsInUse;
bool DeleteStatus;
};
#endif

View file

@ -0,0 +1,350 @@
/*
* Copyright 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 "ShaderParser.h"
#include <stdlib.h>
#include <string.h>
ShaderParser::ShaderParser():ObjectData(SHADER_DATA),
m_type(0),
m_originalSrc(NULL),
m_parsedLines(NULL),
m_deleteStatus(false),
m_program(0) {
m_infoLog = new GLchar[1];
m_infoLog[0] = '\0';
};
ShaderParser::ShaderParser(GLenum type):ObjectData(SHADER_DATA),
m_type(type),
m_originalSrc(NULL),
m_parsedLines(NULL),
m_deleteStatus(false),
m_program(0) {
m_infoLog = new GLchar[1];
m_infoLog[0] = '\0';
};
void ShaderParser::setSrc(const Version& ver,GLsizei count,const GLchar* const* strings,const GLint* length){
m_src.clear();
for(int i = 0;i<count;i++){
m_src.append(strings[i]);
}
//store original source
if (m_originalSrc)
free(m_originalSrc);
m_originalSrc = strdup(m_src.c_str());
clearParsedSrc();
// parseGLSLversion must be called first since #version should be the
// first token in the shader source.
parseGLSLversion();
parseBuiltinConstants();
/*
version 1.30.10 is the first version of GLSL Language containing precision qualifiers
if the glsl version is less than 1.30.10 than we will use a shader parser which omits
all precision qualifiers from the shader source , otherwise we will use a shader parser
which set the default precisions to be the same as the default precisions of GLSL ES
*/
#if 0
if(ver < Version(1,30,10)){
parseOmitPrecision();
} else {
parseExtendDefaultPrecision();
}
#else
//XXX: Until proved otherwise, glsl doesn't know/use those precision macros, so we omit then
parseOmitPrecision();
#endif
parseLineNumbers();
parseOriginalSrc();
}
const GLchar** ShaderParser::parsedLines() {
m_parsedLines = (GLchar*)m_parsedSrc.c_str();
return const_cast<const GLchar**> (&m_parsedLines);
};
const char* ShaderParser::getOriginalSrc(){
return m_originalSrc;
}
void ShaderParser::parseLineNumbers()
{
m_parsedSrc += "#line 1\n";
}
void ShaderParser::parseOriginalSrc() {
m_parsedSrc+=m_src;
}
void ShaderParser::parseGLSLversion() {
//
// find in shader the #version token if exist.
// That token should be the first non-comment or blank token
//
const char *src = m_src.c_str();
const int minGLSLVersion = 120;
int glslVersion = minGLSLVersion;
enum {
PARSE_NONE,
PARSE_IN_C_COMMENT,
PARSE_IN_LINE_COMMENT
} parseState = PARSE_NONE;
const char *c = src;
#define IS_VALID_VERSION(v) ( (v) == 100 || (v) == 300 || (v) == 310 )
while( c && *c != '\0') {
if (parseState == PARSE_IN_C_COMMENT) {
if (*c == '*' && *(c+1) == '/') {
parseState = PARSE_NONE;
c += 2;
}
else c++;
}
else if (parseState == PARSE_IN_LINE_COMMENT) {
if (*c == '\n') {
parseState = PARSE_NONE;
}
c++;
}
else if (*c == '/' && *(c+1) == '/') {
parseState = PARSE_IN_LINE_COMMENT;
c += 2;
}
else if (*c == '/' && *(c+1) == '*') {
parseState = PARSE_IN_C_COMMENT;
c += 2;
}
else if (*c == ' ' || *c == '\t' || *c == '\r' || *c == '\n') {
c++;
}
else {
//
// We have reached the first non-blank character outside
// a comment, this must be a #version token or else #version
// token does not exist in this shader source.
//
if (!strncmp(c,"#version",8)) {
int ver;
if (sscanf(c+8,"%d",&ver) == 1) {
//
// parsed version string correctly, blank out the
// version token from the source, we will add it later at
// the begining of the shader.
//
char *cc = (char *)c;
for (int i=0; i<8; i++,cc++) *cc = ' ';
while (*cc < '0' || *cc > '9') { *cc = ' '; cc++; }
while (*cc >= '0' && *cc <= '9') { *cc = ' '; cc++; }
// Use the version from the source but only if
// it is larger than our minGLSLVersion
if (!IS_VALID_VERSION(ver) || ver > minGLSLVersion) glslVersion = ver;
}
}
//
// break the loop, no need to go further on the source.
break;
}
}
//
// allow to force GLSL version through environment variable
//
const char *forceVersion = getenv("GOOGLE_GLES_FORCE_GLSL_VERSION");
if (forceVersion) {
int ver;
if (sscanf(forceVersion,"%d",&ver) == 1) {
glslVersion = ver;
}
}
//
// if glslVersion is defined, add it to the parsed source
//
if (glslVersion > 0) {
char vstr[16];
sprintf(vstr,"%d",glslVersion);
m_parsedSrc += std::string("#version ") +
std::string(vstr) +
std::string("\n");
}
}
void ShaderParser::parseBuiltinConstants()
{
m_parsedSrc +=
"const int _translator_gl_MaxVertexUniformVectors = 256;\n"
"const int _translator_gl_MaxFragmentUniformVectors = 256;\n"
"const int _translator_gl_MaxVaryingVectors = 15;\n"
"#define gl_MaxVertexUniformVectors _translator_gl_MaxVertexUniformVectors\n"
"#define gl_MaxFragmentUniformVectors _translator_gl_MaxFragmentUniformVectors\n"
"#define gl_MaxVaryingVectors _translator_gl_MaxVaryingVectors\n";
}
void ShaderParser::parseOmitPrecision(){
//defines we need to add in order to Omit precisions qualifiers
static const GLchar defines[] = {
"#define GLES 1\n"
"#define lowp \n"
"#define mediump \n"
"#define highp \n"
};
m_parsedSrc+=defines;
//
// parse the source and blank out precision statements
// which has the following syntax:
// precision {qualifier} {type};
// where {qualifier} is one of lowp,mediump or hightp
// type is any valid GLES defined type (we do not check that here!)
// NOTE: This is needed in order to workaround driver bug in
// Intel/Linux where the compiler does not get statement like
// "float;", otherwise we could just define a macro named
// precision to be empty.
//
const char *src = m_src.c_str();
enum {
PRECISION,
QUALIFIER,
SEMICOLON
} statementState = PRECISION;
const char *precision = NULL;
enum {
PARSE_NONE,
PARSE_IN_C_COMMENT,
PARSE_IN_LINE_COMMENT
} parseState = PARSE_NONE;
const char *c = src;
const char *t = NULL;
#define IS_DELIMITER(c) ( (c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n' )
#define IS_TOKEN_START(c) ( ((c) >= 'a' && (c) <='z') || ((c) >= 'A' && (c) <= 'Z') )
#define IS_TOKEN_DELIMITER(c) ( IS_DELIMITER(c) || (c) == ';' )
while( c && *c != '\0') {
if (parseState == PARSE_IN_C_COMMENT) {
if (*c == '*' && *(c+1) == '/') {
parseState = PARSE_NONE;
c += 2;
}
else c++;
}
else if (parseState == PARSE_IN_LINE_COMMENT) {
if (*c == '\n') {
parseState = PARSE_NONE;
}
c++;
}
else if (*c == '/' && *(c+1) == '/') {
parseState = PARSE_IN_LINE_COMMENT;
c += 2;
}
else if (*c == '/' && *(c+1) == '*') {
parseState = PARSE_IN_C_COMMENT;
c += 2;
}
else if (t && IS_TOKEN_DELIMITER(*c)) {
int tokenLen = c - t;
switch (statementState) {
case PRECISION:
if (tokenLen == 9 && !strncmp(t,"precision",9)) {
statementState = QUALIFIER;
precision = t;
}
break;
case QUALIFIER:
if ((tokenLen == 4 && !strncmp(t,"lowp",4)) ||
(tokenLen == 7 && !strncmp(t,"mediump",7)) ||
(tokenLen == 5 && !strncmp(t,"highp",5))) {
statementState = SEMICOLON;
}
else {
statementState = PRECISION;
}
break;
case SEMICOLON:
if (*c == ';') {
for (char *r = (char *)precision; r<=c ; ++r) {
*r = ' '; //blank the character
}
}
statementState = PRECISION; //search for the next precision line
break;
default:
break;
}
c++;
t = NULL;
}
else if (IS_DELIMITER(*c)) {
c++;
}
else {
if (!t && IS_TOKEN_START(*c)) {
t = c;
}
c++;
}
}
}
void ShaderParser::parseExtendDefaultPrecision(){
//the precision lines which we need to add to the shader
static const GLchar extend[] = {
"#define GLES 1\n"
"precision lowp sampler2D;\n"
"precision lowp samplerCube;\n"
};
m_parsedSrc+=extend;
}
void ShaderParser::clearParsedSrc(){
m_parsedSrc.clear();
}
GLenum ShaderParser::getType() {
return m_type;
}
void ShaderParser::setInfoLog(GLchar* infoLog)
{
delete[] m_infoLog;
m_infoLog = infoLog;
}
GLchar* ShaderParser::getInfoLog()
{
return m_infoLog;
}
ShaderParser::~ShaderParser(){
clearParsedSrc();
if (m_originalSrc)
free(m_originalSrc);
delete[] m_infoLog;
}

View file

@ -0,0 +1,61 @@
/*
* Copyright 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.
*/
#ifndef SHADER_PARSER_H
#define SHADER_PARSER_H
#include "GLESv2Context.h"
#include <string>
#include <GLES2/gl2.h>
#include <GLcommon/objectNameManager.h>
class ShaderParser:public ObjectData{
public:
ShaderParser();
ShaderParser(GLenum type);
void setSrc(const Version& ver,GLsizei count,const GLchar* const* strings,const GLint* length);
const char* getOriginalSrc();
const GLchar** parsedLines();
GLenum getType();
~ShaderParser();
void setInfoLog(GLchar * infoLog);
GLchar* getInfoLog();
void setDeleteStatus(bool val) { m_deleteStatus = val; }
bool getDeleteStatus() const { return m_deleteStatus; }
void setAttachedProgram(GLuint program) { m_program = program; }
GLuint getAttachedProgram() const { return m_program; }
private:
void parseOriginalSrc();
void parseGLSLversion();
void parseBuiltinConstants();
void parseOmitPrecision();
void parseExtendDefaultPrecision();
void parseLineNumbers();
void clearParsedSrc();
GLenum m_type;
char* m_originalSrc;
std::string m_src;
std::string m_parsedSrc;
GLchar* m_parsedLines;
GLchar* m_infoLog;
bool m_deleteStatus;
GLuint m_program;
};
#endif

View file

@ -0,0 +1,43 @@
LOCAL_PATH := $(call my-dir)
host_common_SRC_FILES := \
GLDispatch.cpp \
GLutils.cpp \
GLEScontext.cpp \
GLESvalidate.cpp \
GLESpointer.cpp \
GLESbuffer.cpp \
RangeManip.cpp \
TextureUtils.cpp \
PaletteTexture.cpp \
etc1.cpp \
objectNameManager.cpp \
FramebufferData.cpp
host_GL_COMMON_LINKER_FLAGS :=
host_common_LDLIBS :=
host_common_LDFLAGS :=
ifeq ($(BUILD_TARGET_OS),linux)
# host_common_LDFLAGS += -Wl,--whole-archive
host_common_LDLIBS += -ldl
host_common_LDFLAGS += -Wl,-Bsymbolic
endif
ifeq ($(BUILD_TARGET_OS),windows)
host_common_LDLIBS += -lgdi32
host_common_LDFLAGS += -Wl,--add-stdcall-alias
endif
### EGL host implementation ########################
$(call emugl-begin-host-static-library,libGLcommon)
LOCAL_SRC_FILES := $(host_common_SRC_FILES)
$(call emugl-export,LDLIBS,$(host_common_LDLIBS))
$(call emugl-export,LDFLAGS,$(host_common_LDFLAGS))
$(call emugl-export,C_INCLUDES,$(LOCAL_PATH)/../include $(EMUGL_PATH)/shared)
$(call emugl-export,STATIC_LIBRARIES, libemugl_common)
$(call emugl-end-module)

View file

@ -0,0 +1,17 @@
set(SOURCES
GLDispatch.cpp
GLutils.cpp
GLEScontext.cpp
GLESvalidate.cpp
GLESpointer.cpp
GLESbuffer.cpp
RangeManip.cpp
TextureUtils.cpp
PaletteTexture.cpp
etc1.cpp
objectNameManager.cpp
FramebufferData.cpp)
add_library(GLcommon ${SOURCES})
target_link_libraries(GLcommon
emugl_common)

View file

@ -0,0 +1,215 @@
/*
* 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 <GLES/gl.h>
#include <GLES/glext.h>
#include <GLcommon/FramebufferData.h>
#include <GLcommon/GLEScontext.h>
RenderbufferData::RenderbufferData() : sourceEGLImage(0),
eglImageDetach(NULL),
attachedFB(0),
attachedPoint(0),
eglImageGlobalTexName(0) {
}
RenderbufferData::~RenderbufferData() {
if (sourceEGLImage && eglImageDetach) (*eglImageDetach)(sourceEGLImage);
}
FramebufferData::FramebufferData(GLuint name):m_dirty(false) {
m_fbName = name;
for (int i=0; i<MAX_ATTACH_POINTS; i++) {
m_attachPoints[i].target = 0;
m_attachPoints[i].name = 0;
m_attachPoints[i].obj = ObjectDataPtr(NULL);
m_attachPoints[i].owned = false;
}
}
FramebufferData::~FramebufferData() {
for (int i=0; i<MAX_ATTACH_POINTS; i++) {
detachObject(i);
}
}
void FramebufferData::setAttachment(GLenum attachment,
GLenum target,
GLuint name,
ObjectDataPtr obj,
bool takeOwnership) {
int idx = attachmentPointIndex(attachment);
if (!name) {
detachObject(idx);
return;
}
if (m_attachPoints[idx].target != target ||
m_attachPoints[idx].name != name ||
m_attachPoints[idx].obj.Ptr() != obj.Ptr() ||
m_attachPoints[idx].owned != takeOwnership) {
detachObject(idx);
m_attachPoints[idx].target = target;
m_attachPoints[idx].name = name;
m_attachPoints[idx].obj = obj;
m_attachPoints[idx].owned = takeOwnership;
if (target == GL_RENDERBUFFER_OES && obj.Ptr() != NULL) {
RenderbufferData *rbData = (RenderbufferData *)obj.Ptr();
rbData->attachedFB = m_fbName;
rbData->attachedPoint = attachment;
}
m_dirty = true;
}
}
GLuint FramebufferData::getAttachment(GLenum attachment,
GLenum *outTarget,
ObjectDataPtr *outObj) {
int idx = attachmentPointIndex(attachment);
if (outTarget) *outTarget = m_attachPoints[idx].target;
if (outObj) *outObj = m_attachPoints[idx].obj;
return m_attachPoints[idx].name;
}
int FramebufferData::attachmentPointIndex(GLenum attachment)
{
switch(attachment) {
case GL_COLOR_ATTACHMENT0_OES:
return 0;
case GL_DEPTH_ATTACHMENT_OES:
return 1;
case GL_STENCIL_ATTACHMENT_OES:
return 2;
default:
return MAX_ATTACH_POINTS;
}
}
void FramebufferData::detachObject(int idx) {
if (m_attachPoints[idx].target == GL_RENDERBUFFER_OES && m_attachPoints[idx].obj.Ptr() != NULL) {
RenderbufferData *rbData = (RenderbufferData *)m_attachPoints[idx].obj.Ptr();
rbData->attachedFB = 0;
rbData->attachedPoint = 0;
}
if(m_attachPoints[idx].owned)
{
switch(m_attachPoints[idx].target)
{
case GL_RENDERBUFFER_OES:
GLEScontext::dispatcher().glDeleteRenderbuffersEXT(1, &(m_attachPoints[idx].name));
break;
case GL_TEXTURE_2D:
GLEScontext::dispatcher().glDeleteTextures(1, &(m_attachPoints[idx].name));
break;
}
}
m_attachPoints[idx].target = 0;
m_attachPoints[idx].name = 0;
m_attachPoints[idx].obj = ObjectDataPtr(NULL);
m_attachPoints[idx].owned = false;
}
void FramebufferData::validate(GLEScontext* ctx)
{
if(!getAttachment(GL_COLOR_ATTACHMENT0_OES, NULL, NULL))
{
// GLES does not require the framebuffer to have a color attachment.
// OpenGL does. Therefore, if no color is attached, create a dummy
// color texture and attach it.
// This dummy color texture will is owned by the FramebufferObject,
// and will be released by it when its object is detached.
GLint type = GL_NONE;
GLint name = 0;
ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_OES, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
if(type != GL_NONE)
{
ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_OES, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &name);
}
else
{
ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT_OES, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
if(type != GL_NONE)
{
ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT_OES, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &name);
}
else
{
// No color, depth or stencil attachments - do nothing
return;
}
}
// Find the existing attachment(s) dimensions
GLint width = 0;
GLint height = 0;
if(type == GL_RENDERBUFFER)
{
GLint prev;
ctx->dispatcher().glGetIntegerv(GL_RENDERBUFFER_BINDING, &prev);
ctx->dispatcher().glBindRenderbufferEXT(GL_RENDERBUFFER, name);
ctx->dispatcher().glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
ctx->dispatcher().glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
ctx->dispatcher().glBindRenderbufferEXT(GL_RENDERBUFFER, prev);
}
else if(type == GL_TEXTURE)
{
GLint prev;
ctx->dispatcher().glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, name);
ctx->dispatcher().glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
ctx->dispatcher().glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, prev);
}
// Create the color attachment and attch it
unsigned int tex = ctx->shareGroup()->genGlobalName(TEXTURE);
GLint prev;
ctx->dispatcher().glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, tex);
ctx->dispatcher().glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
ctx->dispatcher().glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
ctx->dispatcher().glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
ctx->dispatcher().glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
ctx->dispatcher().glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
ctx->dispatcher().glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tex, 0);
setAttachment(GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tex, ObjectDataPtr(NULL), true);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, prev);
}
if(m_dirty)
{
// This is a workaround for a bug found in several OpenGL
// drivers (e.g. ATI's) - after the framebuffer attachments
// have changed, and before the next draw, unbind and rebind
// the framebuffer to sort things out.
ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER,0);
ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER,ctx->shareGroup()->getGlobalName(FRAMEBUFFER,m_fbName));
m_dirty = false;
}
}

View file

@ -0,0 +1,117 @@
/*
* 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 "GLcommon/GLDispatch.h"
#include "GLcommon/GLLibrary.h"
#include "emugl/common/lazy_instance.h"
#include "emugl/common/shared_library.h"
#include "OpenglCodecCommon/ErrorLog.h"
#ifdef __linux__
#include <GL/glx.h>
#elif defined(WIN32)
#include <windows.h>
#endif
#include <stdio.h>
typedef GlLibrary::GlFunctionPointer GL_FUNC_PTR;
static GL_FUNC_PTR getGLFuncAddress(const char *funcName, GlLibrary* glLib) {
return glLib->findSymbol(funcName);
}
#define LOAD_GL_FUNC(return_type, func_name, signature, args) do { \
if (!func_name) { \
void* address = (void *)getGLFuncAddress(#func_name, glLib); \
if (address) { \
func_name = (__typeof__(func_name))(address); \
} else { \
fprintf(stderr, "Could not load func %s\n", #func_name); \
func_name = (__typeof__(func_name))(dummy_##func_name); \
} \
} \
} while (0);
#define LOAD_GLEXT_FUNC(return_type, func_name, signature, args) do { \
if (!func_name) { \
void* address = (void *)getGLFuncAddress(#func_name, glLib); \
if (address) { \
func_name = (__typeof__(func_name))(address); \
} \
} \
} while (0);
// Define dummy functions, only for non-extensions.
#define RETURN_void return
#define RETURN_GLboolean return GL_FALSE
#define RETURN_GLint return 0
#define RETURN_GLuint return 0U
#define RETURN_GLenum return 0
#define RETURN_int return 0
#define RETURN_GLconstubyteptr return NULL
#define RETURN_(x) RETURN_ ## x
#define DEFINE_DUMMY_FUNCTION(return_type, func_name, signature, args) \
static return_type dummy_##func_name signature { \
RETURN_(return_type); \
}
#define DEFINE_DUMMY_EXTENSION_FUNCTION(return_type, func_name, signature, args) \
// nothing here
LIST_GLES_FUNCTIONS(DEFINE_DUMMY_FUNCTION, DEFINE_DUMMY_EXTENSION_FUNCTION)
// Initializing static GLDispatch members*/
emugl::Mutex GLDispatch::s_lock;
#define GL_DISPATCH_DEFINE_POINTER(return_type, function_name, signature, args) \
GL_APICALL return_type (GL_APIENTRY *GLDispatch::function_name) signature = NULL;
LIST_GLES_FUNCTIONS(GL_DISPATCH_DEFINE_POINTER, GL_DISPATCH_DEFINE_POINTER)
// Constructor.
GLDispatch::GLDispatch() : m_isLoaded(false) {}
void GLDispatch::dispatchFuncs(GLESVersion version, GlLibrary* glLib) {
emugl::Mutex::AutoLock mutex(s_lock);
if(m_isLoaded)
return;
/* Loading OpenGL functions which are needed for implementing BOTH GLES 1.1 & GLES 2.0*/
LIST_GLES_COMMON_FUNCTIONS(LOAD_GL_FUNC)
LIST_GLES_EXTENSIONS_FUNCTIONS(LOAD_GLEXT_FUNC)
/* Loading OpenGL functions which are needed ONLY for implementing GLES 1.1*/
if(version == GLES_1_1){
LIST_GLES1_ONLY_FUNCTIONS(LOAD_GL_FUNC)
LIST_GLES1_EXTENSIONS_FUNCTIONS(LOAD_GLEXT_FUNC)
} else if (version == GLES_2_0){
LIST_GLES2_ONLY_FUNCTIONS(LOAD_GL_FUNC)
LIST_GLES2_EXTENSIONS_FUNCTIONS(LOAD_GLEXT_FUNC)
}
/* Load glGetStringi() if it is available, so use LOAD_GLEXT_FUNC */
LIST_GLES3_ONLY_FUNCTIONS(LOAD_GLEXT_FUNC)
m_isLoaded = true;
}

View file

@ -0,0 +1,55 @@
/*
* 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 <GLcommon/GLESbuffer.h>
#include <string.h>
bool GLESbuffer::setBuffer(GLuint size,GLuint usage,const GLvoid* data) {
m_size = size;
m_usage = usage;
if(m_data) {
delete [] m_data;
m_data = NULL;
}
m_data = new unsigned char[size];
if(m_data) {
if(data) {
memcpy(m_data,data,size);
}
m_conversionManager.clear();
m_conversionManager.addRange(Range(0,m_size));
return true;
}
return false;
}
bool GLESbuffer::setSubBuffer(GLint offset,GLuint size,const GLvoid* data) {
if(offset + size > m_size) return false;
memcpy(m_data+offset,data,size);
m_conversionManager.addRange(Range(offset,size));
m_conversionManager.merge();
return true;
}
void GLESbuffer::getConversions(const RangeList& rIn,RangeList& rOut) {
m_conversionManager.delRanges(rIn,rOut);
rOut.merge();
}
GLESbuffer::~GLESbuffer() {
if(m_data) {
delete [] m_data;
}
}

View file

@ -0,0 +1,865 @@
/*
* Copyright 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 <GLcommon/GLEScontext.h>
#include <GLcommon/GLconversion_macros.h>
#include <GLcommon/GLESmacros.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <OpenglCodecCommon/ErrorLog.h>
#include <GLcommon/GLESvalidate.h>
#include <GLcommon/TextureUtils.h>
#include <GLcommon/FramebufferData.h>
#include <strings.h>
#include <string.h>
//decleration
static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
GLESConversionArrays::~GLESConversionArrays() {
for(std::map<GLenum,ArrayData>::iterator it = m_arrays.begin(); it != m_arrays.end();it++) {
if((*it).second.allocated){
if((*it).second.type == GL_FLOAT){
GLfloat* p = (GLfloat *)((*it).second.data);
if(p) delete[] p;
} else if((*it).second.type == GL_SHORT){
GLshort* p = (GLshort *)((*it).second.data);
if(p) delete[] p;
}
}
}
}
void GLESConversionArrays::allocArr(unsigned int size,GLenum type){
if(type == GL_FIXED){
m_arrays[m_current].data = new GLfloat[size];
m_arrays[m_current].type = GL_FLOAT;
} else if(type == GL_BYTE){
m_arrays[m_current].data = new GLshort[size];
m_arrays[m_current].type = GL_SHORT;
}
m_arrays[m_current].stride = 0;
m_arrays[m_current].allocated = true;
}
void GLESConversionArrays::setArr(void* data,unsigned int stride,GLenum type){
m_arrays[m_current].type = type;
m_arrays[m_current].data = data;
m_arrays[m_current].stride = stride;
m_arrays[m_current].allocated = false;
}
void* GLESConversionArrays::getCurrentData(){
return m_arrays[m_current].data;
}
ArrayData& GLESConversionArrays::getCurrentArray(){
return m_arrays[m_current];
}
unsigned int GLESConversionArrays::getCurrentIndex(){
return m_current;
}
ArrayData& GLESConversionArrays::operator[](int i){
return m_arrays[i];
}
void GLESConversionArrays::operator++(){
m_current++;
}
GLDispatch GLEScontext::s_glDispatch;
emugl::Mutex GLEScontext::s_lock;
std::string* GLEScontext::s_glExtensions= NULL;
std::string GLEScontext::s_glVendor;
std::string GLEScontext::s_glRenderer;
std::string GLEScontext::s_glVersion;
GLSupport GLEScontext::s_glSupport;
Version::Version():m_major(0),
m_minor(0),
m_release(0){};
Version::Version(int major,int minor,int release):m_major(major),
m_minor(minor),
m_release(release){};
Version::Version(const Version& ver):m_major(ver.m_major),
m_minor(ver.m_minor),
m_release(ver.m_release){}
Version::Version(const char* versionString){
m_release = 0;
if((!versionString) ||
((!(sscanf(versionString,"%d.%d" ,&m_major,&m_minor) == 2)) &&
(!(sscanf(versionString,"%d.%d.%d",&m_major,&m_minor,&m_release) == 3)))){
m_major = m_minor = 0; // the version is not in the right format
}
}
Version& Version::operator=(const Version& ver){
m_major = ver.m_major;
m_minor = ver.m_minor;
m_release = ver.m_release;
return *this;
}
bool Version::operator<(const Version& ver) const{
if(m_major < ver.m_major) return true;
if(m_major == ver.m_major){
if(m_minor < ver.m_minor) return true;
if(m_minor == ver.m_minor){
return m_release < ver.m_release;
}
}
return false;
}
static std::string getHostExtensionsString(GLDispatch* dispatch) {
// glGetString(GL_EXTENSIONS) is deprecated in GL 3.0, one has to use
// glGetStringi(GL_EXTENSIONS, index) instead to get individual extension
// names. Recent desktop drivers implement glGetStringi() but have a
// version of glGetString() that returns NULL, so deal with this by
// doing the following:
//
// - If glGetStringi() is available, and glGetIntegerv(GL_NUM_EXTENSIONS &num_exts)
// gives a nonzero value, use it to build the extensions
// string, using simple spaces to separate the names.
//
// - Otherwise, fallback to getGetString(). If it returns NULL, return
// an empty string.
//
std::string result;
int num_exts = 0;
if (dispatch->glGetStringi) {
dispatch->glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts);
GLenum err = dispatch->glGetError();
if (err == GL_NO_ERROR) {
for (int n = 0; n < num_exts; n++) {
const char* ext = reinterpret_cast<const char*>(
dispatch->glGetStringi(GL_EXTENSIONS, n));
if (ext != NULL) {
if (!result.empty()) {
result += " ";
}
result += ext;
}
}
}
}
// If glGetIntegerv does not affect the value,
// our system does not actually support
// GL 3.0 style extension getting.
if (!dispatch->glGetStringi || num_exts == 0) {
const char* extensions = reinterpret_cast<const char*>(
dispatch->glGetString(GL_EXTENSIONS));
if (extensions) {
result = extensions;
}
}
// For the sake of initCapsLocked() add a starting and trailing space.
if (!result.empty()) {
if (result[0] != ' ') {
result.insert(0, 1, ' ');
}
if (result[result.size() - 1U] != ' ') {
result += ' ';
}
}
return result;
}
static GLuint getIndex(GLenum indices_type, const GLvoid* indices, unsigned int i) {
switch (indices_type) {
case GL_UNSIGNED_BYTE:
return static_cast<const GLubyte*>(indices)[i];
case GL_UNSIGNED_SHORT:
return static_cast<const GLushort*>(indices)[i];
case GL_UNSIGNED_INT:
return static_cast<const GLuint*>(indices)[i];
default:
ERR("**** ERROR unknown type 0x%x (%s,%d)\n", indices_type, __FUNCTION__,__LINE__);
return 0;
}
}
void GLEScontext::init(GlLibrary* glLib) {
if (!s_glExtensions) {
initCapsLocked(reinterpret_cast<const GLubyte*>(
getHostExtensionsString(&s_glDispatch).c_str()));
// NOTE: the string below corresponds to the extensions reported
// by this context, which is initialized in each GLESv1 or GLESv2
// context implementation, based on the parsing of the host
// extensions string performed by initCapsLocked(). I.e. it will
// be populated after calling this ::init() method.
s_glExtensions = new std::string("");
}
if (!m_initialized) {
initExtensionString();
int maxTexUnits = getMaxTexUnits();
m_texState = new textureUnitState[maxTexUnits];
for (int i=0;i<maxTexUnits;++i) {
for (int j=0;j<NUM_TEXTURE_TARGETS;++j)
{
m_texState[i][j].texture = 0;
m_texState[i][j].enabled = GL_FALSE;
}
}
}
}
GLEScontext::GLEScontext():
m_initialized(false) ,
m_activeTexture(0) ,
m_unpackAlignment(4) ,
m_glError(GL_NO_ERROR) ,
m_texState(0) ,
m_arrayBuffer(0) ,
m_elementBuffer(0),
m_renderbuffer(0),
m_framebuffer(0)
{
};
GLenum GLEScontext::getGLerror() {
return m_glError;
}
void GLEScontext::setGLerror(GLenum err) {
m_glError = err;
}
void GLEScontext::setActiveTexture(GLenum tex) {
m_activeTexture = tex - GL_TEXTURE0;
}
GLEScontext::~GLEScontext() {
for(ArraysMap::iterator it = m_map.begin(); it != m_map.end();it++) {
GLESpointer* p = (*it).second;
if(p) {
delete p;
}
}
delete[] m_texState;
m_texState = NULL;
}
const GLvoid* GLEScontext::setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize) {
GLuint bufferName = m_arrayBuffer;
if(bufferName) {
unsigned int offset = SafeUIntFromPointer(data);
GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
m_map[arrType]->setBuffer(size,type,stride,vbo,bufferName,offset,normalize);
return static_cast<const unsigned char*>(vbo->getData()) + offset;
}
m_map[arrType]->setArray(size,type,stride,data,normalize);
return data;
}
void GLEScontext::enableArr(GLenum arr,bool enable) {
m_map[arr]->enable(enable);
}
bool GLEScontext::isArrEnabled(GLenum arr) {
return m_map[arr]->isEnable();
}
const GLESpointer* GLEScontext::getPointer(GLenum arrType) {
if (m_map.find(arrType) != m_map.end()) return m_map[arrType];
return NULL;
}
static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) {
for(unsigned int i = 0; i < nBytes;i+=strideOut) {
const GLfixed* fixed_data = (const GLfixed *)dataIn;
//filling attrib
for(int j=0;j<attribSize;j++) {
reinterpret_cast<GLfloat*>(&static_cast<unsigned char*>(dataOut)[i])[j] = X2F(fixed_data[j]);
}
dataIn += strideIn;
}
}
static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) {
for(int i = 0 ;i < count ;i++) {
GLuint index = getIndex(indices_type, indices, i);
const GLfixed* fixed_data = (GLfixed *)(dataIn + index*strideIn);
GLfloat* float_data = reinterpret_cast<GLfloat*>(static_cast<unsigned char*>(dataOut) + index*strideOut);
for(int j=0;j<attribSize;j++) {
float_data[j] = X2F(fixed_data[j]);
}
}
}
static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) {
for(unsigned int i = 0; i < nBytes;i+=strideOut) {
const GLbyte* byte_data = (const GLbyte *)dataIn;
//filling attrib
for(int j=0;j<attribSize;j++) {
reinterpret_cast<GLshort*>(&static_cast<unsigned char*>(dataOut)[i])[j] = B2S(byte_data[j]);
}
dataIn += strideIn;
}
}
static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) {
for(int i = 0 ;i < count ;i++) {
GLuint index = getIndex(indices_type, indices, i);
const GLbyte* bytes_data = (GLbyte *)(dataIn + index*strideIn);
GLshort* short_data = reinterpret_cast<GLshort*>(static_cast<unsigned char*>(dataOut) + index*strideOut);
for(int j=0;j<attribSize;j++) {
short_data[j] = B2S(bytes_data[j]);
}
}
}
static void directToBytesRanges(GLint first,GLsizei count,GLESpointer* p,RangeList& list) {
int attribSize = p->getSize()*4; //4 is the sizeof GLfixed or GLfloat in bytes
int stride = p->getStride()?p->getStride():attribSize;
int start = p->getBufferOffset()+first*attribSize;
if(!p->getStride()) {
list.addRange(Range(start,count*attribSize));
} else {
for(int i = 0 ;i < count; i++,start+=stride) {
list.addRange(Range(start,attribSize));
}
}
}
static void indirectToBytesRanges(const GLvoid* indices,GLenum indices_type,GLsizei count,GLESpointer* p,RangeList& list) {
int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes
int stride = p->getStride()?p->getStride():attribSize;
int start = p->getBufferOffset();
for(int i=0 ; i < count; i++) {
GLuint index = getIndex(indices_type, indices, i);
list.addRange(Range(start+index*stride,attribSize));
}
}
int bytesRangesToIndices(RangeList& ranges,GLESpointer* p,GLuint* indices) {
int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes
int stride = p->getStride()?p->getStride():attribSize;
int offset = p->getBufferOffset();
int n = 0;
for(int i=0;i<ranges.size();i++) {
int startIndex = (ranges[i].getStart() - offset) / stride;
int nElements = ranges[i].getSize()/attribSize;
for(int j=0;j<nElements;j++) {
indices[n++] = startIndex+j;
}
}
return n;
}
void GLEScontext::convertDirect(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) {
GLenum type = p->getType();
int attribSize = p->getSize();
unsigned int size = attribSize*count + first;
unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte);
cArrs.allocArr(size,type);
int stride = p->getStride()?p->getStride():bytes*attribSize;
const char* data = (const char*)p->getArrayData() + (first*stride);
if(type == GL_FIXED) {
convertFixedDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLfloat),attribSize*sizeof(GLfloat),attribSize);
} else if(type == GL_BYTE) {
convertByteDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLshort),attribSize*sizeof(GLshort),attribSize);
}
}
void GLEScontext::convertDirectVBO(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) {
RangeList ranges;
RangeList conversions;
GLuint* indices = NULL;
int attribSize = p->getSize();
int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize;
char* data = (char*)p->getBufferData() + (first*stride);
if(p->bufferNeedConversion()) {
directToBytesRanges(first,count,p,ranges); //converting indices range to buffer bytes ranges by offset
p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted
if(conversions.size()) { // there are some elements to convert
indices = new GLuint[count];
int nIndices = bytesRangesToIndices(conversions,p,indices); //converting bytes ranges by offset to indices in this array
convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_INT,indices,stride,attribSize);
}
}
if(indices) delete[] indices;
cArrs.setArr(data,p->getStride(),GL_FLOAT);
}
unsigned int GLEScontext::findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices) {
//finding max index
unsigned int max = 0;
if(type == GL_UNSIGNED_BYTE) {
GLubyte* b_indices =(GLubyte *)indices;
for(int i=0;i<count;i++) {
if(b_indices[i] > max) max = b_indices[i];
}
} else if (type == GL_UNSIGNED_SHORT) {
GLushort* us_indices =(GLushort *)indices;
for(int i=0;i<count;i++) {
if(us_indices[i] > max) max = us_indices[i];
}
} else { // type == GL_UNSIGNED_INT
GLuint* ui_indices =(GLuint *)indices;
for(int i=0;i<count;i++) {
if(ui_indices[i] > max) max = ui_indices[i];
}
}
return max;
}
void GLEScontext::convertIndirect(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) {
GLenum type = p->getType();
int maxElements = findMaxIndex(count,indices_type,indices) + 1;
int attribSize = p->getSize();
int size = attribSize * maxElements;
unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte);
cArrs.allocArr(size,type);
int stride = p->getStride()?p->getStride():bytes*attribSize;
const char* data = (const char*)p->getArrayData();
if(type == GL_FIXED) {
convertFixedIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLfloat),attribSize);
} else if(type == GL_BYTE){
convertByteIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLshort),attribSize);
}
}
void GLEScontext::convertIndirectVBO(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) {
RangeList ranges;
RangeList conversions;
GLuint* conversionIndices = NULL;
int attribSize = p->getSize();
int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize;
char* data = static_cast<char*>(p->getBufferData());
if(p->bufferNeedConversion()) {
indirectToBytesRanges(indices,indices_type,count,p,ranges); //converting indices range to buffer bytes ranges by offset
p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted
if(conversions.size()) { // there are some elements to convert
conversionIndices = new GLuint[count];
int nIndices = bytesRangesToIndices(conversions,p,conversionIndices); //converting bytes ranges by offset to indices in this array
convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_INT,conversionIndices,stride,attribSize);
}
}
if(conversionIndices) delete[] conversionIndices;
cArrs.setArr(data,p->getStride(),GL_FLOAT);
}
void GLEScontext::bindBuffer(GLenum target,GLuint buffer) {
if(target == GL_ARRAY_BUFFER) {
m_arrayBuffer = buffer;
} else {
m_elementBuffer = buffer;
}
}
void GLEScontext::unbindBuffer(GLuint buffer) {
if(m_arrayBuffer == buffer)
{
m_arrayBuffer = 0;
}
if(m_elementBuffer == buffer)
{
m_elementBuffer = 0;
}
}
//checks if any buffer is binded to target
bool GLEScontext::isBindedBuffer(GLenum target) {
if(target == GL_ARRAY_BUFFER) {
return m_arrayBuffer != 0;
} else {
return m_elementBuffer != 0;
}
}
GLuint GLEScontext::getBuffer(GLenum target) {
return target == GL_ARRAY_BUFFER ? m_arrayBuffer:m_elementBuffer;
}
GLvoid* GLEScontext::getBindedBuffer(GLenum target) {
GLuint bufferName = getBuffer(target);
if(!bufferName) return NULL;
GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
return vbo->getData();
}
void GLEScontext::getBufferSize(GLenum target,GLint* param) {
GLuint bufferName = getBuffer(target);
GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
*param = vbo->getSize();
}
void GLEScontext::getBufferUsage(GLenum target,GLint* param) {
GLuint bufferName = getBuffer(target);
GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
*param = vbo->getUsage();
}
bool GLEScontext::setBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage) {
GLuint bufferName = getBuffer(target);
if(!bufferName) return false;
GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
return vbo->setBuffer(size,usage,data);
}
bool GLEScontext::setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid* data) {
GLuint bufferName = getBuffer(target);
if(!bufferName) return false;
GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
return vbo->setSubBuffer(offset,size,data);
}
const char * GLEScontext::getExtensionString() {
const char * ret;
s_lock.lock();
if (s_glExtensions)
ret = s_glExtensions->c_str();
else
ret="";
s_lock.unlock();
return ret;
}
const char * GLEScontext::getVendorString() const {
return s_glVendor.c_str();
}
const char * GLEScontext::getRendererString() const {
return s_glRenderer.c_str();
}
const char * GLEScontext::getVersionString() const {
return s_glVersion.c_str();
}
void GLEScontext::getGlobalLock() {
s_lock.lock();
}
void GLEScontext::releaseGlobalLock() {
s_lock.unlock();
}
void GLEScontext::initCapsLocked(const GLubyte * extensionString)
{
const char* cstring = (const char*)extensionString;
s_glDispatch.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&s_glSupport.maxVertexAttribs);
s_glDispatch.glGetIntegerv(GL_MAX_CLIP_PLANES,&s_glSupport.maxClipPlane);
s_glDispatch.glGetIntegerv(GL_MAX_LIGHTS,&s_glSupport.maxLights);
s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_SIZE,&s_glSupport.maxTexSize);
s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_UNITS,&s_glSupport.maxTexUnits);
s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&s_glSupport.maxTexImageUnits);
s_glDispatch.glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &s_glSupport.maxCombinedTexImageUnits);
const GLubyte* glslVersion = s_glDispatch.glGetString(GL_SHADING_LANGUAGE_VERSION);
s_glSupport.glslVersion = Version((const char*)(glslVersion));
const GLubyte* glVersion = s_glDispatch.glGetString(GL_VERSION);
if (strstr(cstring,"GL_EXT_bgra ")!=NULL)
s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888 = true;
if (strstr(cstring,"GL_EXT_framebuffer_object ")!=NULL)
s_glSupport.GL_EXT_FRAMEBUFFER_OBJECT = true;
if (strstr(cstring,"GL_ARB_vertex_blend ")!=NULL)
s_glSupport.GL_ARB_VERTEX_BLEND = true;
if (strstr(cstring,"GL_ARB_matrix_palette ")!=NULL)
s_glSupport.GL_ARB_MATRIX_PALETTE = true;
if (strstr(cstring,"GL_EXT_packed_depth_stencil ")!=NULL )
s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL = true;
if (strstr(cstring,"GL_OES_read_format ")!=NULL)
s_glSupport.GL_OES_READ_FORMAT = true;
if (strstr(cstring,"GL_ARB_half_float_pixel ")!=NULL)
s_glSupport.GL_ARB_HALF_FLOAT_PIXEL = true;
if (strstr(cstring,"GL_NV_half_float ")!=NULL)
s_glSupport.GL_NV_HALF_FLOAT = true;
if (strstr(cstring,"GL_ARB_half_float_vertex ")!=NULL)
s_glSupport.GL_ARB_HALF_FLOAT_VERTEX = true;
if (strstr(cstring,"GL_SGIS_generate_mipmap ")!=NULL)
s_glSupport.GL_SGIS_GENERATE_MIPMAP = true;
if (strstr(cstring,"GL_ARB_ES2_compatibility ")!=NULL)
s_glSupport.GL_ARB_ES2_COMPATIBILITY = true;
if (strstr(cstring,"GL_OES_standard_derivatives ")!=NULL)
s_glSupport.GL_OES_STANDARD_DERIVATIVES = true;
if (strstr(cstring,"GL_ARB_texture_non_power_of_two")!=NULL)
s_glSupport.GL_OES_TEXTURE_NPOT = true;
if (!(Version((const char*)glVersion) < Version("3.0")) || strstr(cstring,"GL_OES_rgb8_rgba8")!=NULL)
s_glSupport.GL_OES_RGB8_RGBA8 = true;
}
void GLEScontext::buildStrings(const char* baseVendor,
const char* baseRenderer, const char* baseVersion, const char* version)
{
static const char VENDOR[] = {"Google ("};
static const char RENDERER[] = {"Android Emulator OpenGL ES Translator ("};
const size_t VENDOR_LEN = sizeof(VENDOR) - 1;
const size_t RENDERER_LEN = sizeof(RENDERER) - 1;
// Sanitize the strings as some OpenGL implementations return NULL
// when asked the basic questions (this happened at least once on a client
// machine)
if (!baseVendor) {
baseVendor = "N/A";
}
if (!baseRenderer) {
baseRenderer = "N/A";
}
if (!baseVersion) {
baseVersion = "N/A";
}
if (!version) {
version = "N/A";
}
size_t baseVendorLen = strlen(baseVendor);
s_glVendor.clear();
s_glVendor.reserve(baseVendorLen + VENDOR_LEN + 1);
s_glVendor.append(VENDOR, VENDOR_LEN);
s_glVendor.append(baseVendor, baseVendorLen);
s_glVendor.append(")", 1);
size_t baseRendererLen = strlen(baseRenderer);
s_glRenderer.clear();
s_glRenderer.reserve(baseRendererLen + RENDERER_LEN + 1);
s_glRenderer.append(RENDERER, RENDERER_LEN);
s_glRenderer.append(baseRenderer, baseRendererLen);
s_glRenderer.append(")", 1);
size_t baseVersionLen = strlen(baseVersion);
size_t versionLen = strlen(version);
s_glVersion.clear();
s_glVersion.reserve(baseVersionLen + versionLen + 3);
s_glVersion.append(version, versionLen);
s_glVersion.append(" (", 2);
s_glVersion.append(baseVersion, baseVersionLen);
s_glVersion.append(")", 1);
}
bool GLEScontext::isTextureUnitEnabled(GLenum unit) {
for (int i=0;i<NUM_TEXTURE_TARGETS;++i) {
if (m_texState[unit-GL_TEXTURE0][i].enabled)
return true;
}
return false;
}
bool GLEScontext::glGetBooleanv(GLenum pname, GLboolean *params)
{
GLint iParam;
if(glGetIntegerv(pname, &iParam))
{
*params = (iParam != 0);
return true;
}
return false;
}
bool GLEScontext::glGetFixedv(GLenum pname, GLfixed *params)
{
bool result = false;
GLint numParams = 1;
GLint* iParams = new GLint[numParams];
if (numParams>0 && glGetIntegerv(pname,iParams)) {
while(numParams >= 0)
{
params[numParams] = I2X(iParams[numParams]);
numParams--;
}
result = true;
}
delete [] iParams;
return result;
}
bool GLEScontext::glGetFloatv(GLenum pname, GLfloat *params)
{
bool result = false;
GLint numParams = 1;
GLint* iParams = new GLint[numParams];
if (numParams>0 && glGetIntegerv(pname,iParams)) {
while(numParams >= 0)
{
params[numParams] = (GLfloat)iParams[numParams];
numParams--;
}
result = true;
}
delete [] iParams;
return result;
}
bool GLEScontext::glGetIntegerv(GLenum pname, GLint *params)
{
switch(pname)
{
case GL_ARRAY_BUFFER_BINDING:
*params = m_arrayBuffer;
break;
case GL_ELEMENT_ARRAY_BUFFER_BINDING:
*params = m_elementBuffer;
break;
case GL_TEXTURE_BINDING_CUBE_MAP:
*params = m_texState[m_activeTexture][TEXTURE_CUBE_MAP].texture;
break;
case GL_TEXTURE_BINDING_2D:
*params = m_texState[m_activeTexture][TEXTURE_2D].texture;
break;
case GL_ACTIVE_TEXTURE:
*params = m_activeTexture+GL_TEXTURE0;
break;
case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
*params = GL_UNSIGNED_BYTE;
break;
case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
*params = GL_RGBA;
break;
case GL_MAX_TEXTURE_SIZE:
*params = getMaxTexSize();
break;
default:
return false;
}
return true;
}
TextureTarget GLEScontext::GLTextureTargetToLocal(GLenum target) {
TextureTarget value=TEXTURE_2D;
switch (target) {
case GL_TEXTURE_CUBE_MAP:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
value = TEXTURE_CUBE_MAP;
break;
case GL_TEXTURE_2D:
value = TEXTURE_2D;
break;
}
return value;
}
unsigned int GLEScontext::getBindedTexture(GLenum target) {
TextureTarget pos = GLTextureTargetToLocal(target);
return m_texState[m_activeTexture][pos].texture;
}
unsigned int GLEScontext::getBindedTexture(GLenum unit, GLenum target) {
TextureTarget pos = GLTextureTargetToLocal(target);
return m_texState[unit-GL_TEXTURE0][pos].texture;
}
void GLEScontext::setBindedTexture(GLenum target, unsigned int tex) {
TextureTarget pos = GLTextureTargetToLocal(target);
m_texState[m_activeTexture][pos].texture = tex;
}
void GLEScontext::setTextureEnabled(GLenum target, GLenum enable) {
TextureTarget pos = GLTextureTargetToLocal(target);
m_texState[m_activeTexture][pos].enabled = enable;
}
#define INTERNAL_NAME(x) (x +0x100000000ll);
ObjectLocalName GLEScontext::getDefaultTextureName(GLenum target) {
ObjectLocalName name = 0;
switch (GLTextureTargetToLocal(target)) {
case TEXTURE_2D:
name = INTERNAL_NAME(0);
break;
case TEXTURE_CUBE_MAP:
name = INTERNAL_NAME(1);
break;
default:
name = 0;
break;
}
return name;
}
void GLEScontext::drawValidate(void)
{
if(m_framebuffer == 0)
return;
ObjectDataPtr fbObj = m_shareGroup->getObjectData(FRAMEBUFFER,m_framebuffer);
if (fbObj.Ptr() == NULL)
return;
FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
fbData->validate(this);
}

View file

@ -0,0 +1,109 @@
/*
* 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 <GLcommon/GLESpointer.h>
#include <stdlib.h>
GLESpointer::GLESpointer():m_size(4),
m_type(GL_FLOAT),
m_stride(0),
m_enabled(false),
m_normalize(false),
m_data(NULL),
m_buffer(NULL),
m_bufferName(0),
m_buffOffset(0),
m_isVBO(false){};
GLenum GLESpointer:: getType() const {
return m_type;
}
GLint GLESpointer::getSize() const {
return m_size;
}
GLsizei GLESpointer::getStride() const {
return m_stride;
}
const GLvoid* GLESpointer::getArrayData() const {
return m_data;
}
GLvoid* GLESpointer::getBufferData() const {
return m_buffer ? static_cast<unsigned char*>(m_buffer->getData()) + m_buffOffset : NULL;
}
const GLvoid* GLESpointer::getData() const{
return m_isVBO ? getBufferData():getArrayData();
}
void GLESpointer::redirectPointerData(){
m_data = getBufferData();
}
GLuint GLESpointer::getBufferName() const {
return m_bufferName;
}
unsigned int GLESpointer::getBufferOffset() const {
return m_buffOffset;
}
bool GLESpointer::isEnable() const {
return m_enabled;
}
bool GLESpointer::isNormalize() const {
return m_normalize;
}
bool GLESpointer::isVBO() const {
return m_isVBO;
}
void GLESpointer::enable(bool b) {
m_enabled = b;
}
void GLESpointer::setArray(GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize) {
m_size = size;
m_type = type;
m_stride = stride;
m_data = data;
m_buffer = NULL;
m_bufferName = 0;
m_normalize = normalize;
m_isVBO = false;
}
void GLESpointer::setBuffer(GLint size,GLenum type,GLsizei stride,GLESbuffer* buf,GLuint bufferName,int offset,bool normalize) {
m_size = size;
m_type = type;
m_stride = stride;
m_data = NULL;
m_buffer = buf;
m_bufferName = bufferName;
m_buffOffset = offset;
m_normalize = normalize;
m_isVBO = true;
}
void GLESpointer::getBufferConversions(const RangeList& rl,RangeList& rlOut) {
m_buffer->getConversions(rl,rlOut);
}

View file

@ -0,0 +1,194 @@
/*
* Copyright 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 <GLcommon/GLESvalidate.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <OpenglCodecCommon/ErrorLog.h>
bool GLESvalidate::textureEnum(GLenum e,unsigned int maxTex) {
return e >= GL_TEXTURE0 && e < (GL_TEXTURE0 + maxTex);
}
bool GLESvalidate::pixelType(GLEScontext * ctx, GLenum type) {
if ((ctx && ctx->getCaps()->GL_EXT_PACKED_DEPTH_STENCIL) &&
(type == GL_UNSIGNED_INT_24_8_OES) )
return true;
if (ctx &&
(ctx->getCaps()->GL_ARB_HALF_FLOAT_PIXEL || ctx->getCaps()->GL_NV_HALF_FLOAT) &&
(type == GL_HALF_FLOAT_OES))
return true;
switch(type) {
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_FLOAT:
return true;
}
return false;
}
bool GLESvalidate::pixelOp(GLenum format,GLenum type) {
switch(type) {
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
return format == GL_RGBA;
case GL_UNSIGNED_SHORT_5_6_5:
return format == GL_RGB;
}
return true;
}
bool GLESvalidate::pixelFrmt(GLEScontext* ctx ,GLenum format) {
if (ctx && ctx->getCaps()->GL_EXT_TEXTURE_FORMAT_BGRA8888 && format == GL_BGRA_EXT)
return true;
if (ctx && ctx->getCaps()->GL_EXT_PACKED_DEPTH_STENCIL && format == GL_DEPTH_STENCIL_OES)
return true;
switch(format) {
case GL_ALPHA:
case GL_RGB:
case GL_RGBA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
return true;
}
return false;
}
bool GLESvalidate::bufferTarget(GLenum target) {
return target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER;
}
bool GLESvalidate::bufferUsage(GLenum usage) {
switch(usage) {
case GL_STREAM_DRAW:
case GL_STATIC_DRAW:
case GL_DYNAMIC_DRAW:
return true;
}
return false;
}
bool GLESvalidate::bufferParam(GLenum param) {
return (param == GL_BUFFER_SIZE) || (param == GL_BUFFER_USAGE);
}
bool GLESvalidate::drawMode(GLenum mode) {
switch(mode) {
case GL_POINTS:
case GL_LINE_STRIP:
case GL_LINE_LOOP:
case GL_LINES:
case GL_TRIANGLE_STRIP:
case GL_TRIANGLE_FAN:
case GL_TRIANGLES:
return true;
}
return false;
}
bool GLESvalidate::drawType(GLenum mode) {
return mode == GL_UNSIGNED_BYTE ||
mode == GL_UNSIGNED_SHORT ||
mode == GL_UNSIGNED_INT;
}
bool GLESvalidate::textureTarget(GLenum target) {
return target==GL_TEXTURE_2D || target==GL_TEXTURE_CUBE_MAP;
}
bool GLESvalidate::textureTargetLimited(GLenum target) {
return target==GL_TEXTURE_2D;
}
bool GLESvalidate::textureTargetEx(GLenum target) {
switch(target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES:
case GL_TEXTURE_2D:
return true;
}
return false;
}
bool GLESvalidate::blendEquationMode(GLenum mode){
return mode == GL_FUNC_ADD ||
mode == GL_FUNC_SUBTRACT ||
mode == GL_FUNC_REVERSE_SUBTRACT;
}
bool GLESvalidate::framebufferTarget(GLenum target){
return target == GL_FRAMEBUFFER;
}
bool GLESvalidate::framebufferAttachment(GLenum attachment){
switch(attachment){
case GL_COLOR_ATTACHMENT0:
case GL_DEPTH_ATTACHMENT:
case GL_STENCIL_ATTACHMENT:
return true;
}
return false;
}
bool GLESvalidate::framebufferAttachmentParams(GLenum pname){
switch(pname){
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
return true;
}
return false;
}
bool GLESvalidate::renderbufferTarget(GLenum target){
return target == GL_RENDERBUFFER;
}
bool GLESvalidate::renderbufferParams(GLenum pname){
switch(pname){
case GL_RENDERBUFFER_WIDTH:
case GL_RENDERBUFFER_HEIGHT:
case GL_RENDERBUFFER_INTERNAL_FORMAT:
case GL_RENDERBUFFER_RED_SIZE:
case GL_RENDERBUFFER_GREEN_SIZE:
case GL_RENDERBUFFER_BLUE_SIZE:
case GL_RENDERBUFFER_ALPHA_SIZE:
case GL_RENDERBUFFER_DEPTH_SIZE:
case GL_RENDERBUFFER_STENCIL_SIZE:
return true;
}
return false;
}
bool GLESvalidate::texImgDim(GLsizei width,GLsizei height,int maxTexSize) {
if( width < 0 || height < 0 || width > maxTexSize || height > maxTexSize)
return false;
return isPowerOf2(width) && isPowerOf2(height);
}

View file

@ -0,0 +1,20 @@
/*
* 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 <GLcommon/GLutils.h>
bool isPowerOf2(int num) {
return (num & (num -1)) == 0;
}

View file

@ -0,0 +1,170 @@
/*
* 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 "GLcommon/PaletteTexture.h"
#include <stdio.h>
struct Color
{
Color(unsigned char r, unsigned char g,unsigned char b, unsigned char a):red(r),green(g),blue(b),alpha(a){};
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;
};
void getPaletteInfo(GLenum internalFormat,unsigned int& indexSizeBits,unsigned int& colorSizeBytes,GLenum& colorFrmt) {
colorFrmt = GL_RGB;
switch(internalFormat)
{
case GL_PALETTE4_RGB8_OES:
indexSizeBits = 4;
colorSizeBytes = 3;
break;
case GL_PALETTE4_RGBA8_OES:
indexSizeBits = 4;
colorSizeBytes = 4;
colorFrmt = GL_RGBA;
break;
case GL_PALETTE4_RGBA4_OES:
case GL_PALETTE4_RGB5_A1_OES:
colorFrmt = GL_RGBA;
/* fall-through */
case GL_PALETTE4_R5_G6_B5_OES:
indexSizeBits = 4;
colorSizeBytes = 2;
break;
case GL_PALETTE8_RGB8_OES:
indexSizeBits = 8;
colorSizeBytes = 3;
break;
case GL_PALETTE8_RGBA8_OES:
indexSizeBits = 8;
colorSizeBytes = 4;
colorFrmt = GL_RGBA;
break;
case GL_PALETTE8_RGBA4_OES:
case GL_PALETTE8_RGB5_A1_OES:
colorFrmt = GL_RGBA;
/* fall-through */
case GL_PALETTE8_R5_G6_B5_OES:
indexSizeBits = 8;
colorSizeBytes = 2;
break;
}
}
Color paletteColor(const unsigned char* pallete,unsigned int index,GLenum format)
{
short s;
switch(format) {
//RGB
case GL_PALETTE4_RGB8_OES:
case GL_PALETTE8_RGB8_OES:
return Color(pallete[index],pallete[index+1],pallete[index+2],0);
case GL_PALETTE8_R5_G6_B5_OES:
case GL_PALETTE4_R5_G6_B5_OES:
s = *((short *)(pallete+index));
return Color((s >> 11)*255/31,((s >> 5) & 0x3f)*255/63 ,(s & 0x1f)*255/31,0);
//RGBA
case GL_PALETTE4_RGBA8_OES:
case GL_PALETTE8_RGBA8_OES:
return Color(pallete[index],pallete[index+1],pallete[index+2],pallete[index+3]);
case GL_PALETTE4_RGBA4_OES:
case GL_PALETTE8_RGBA4_OES:
s = *((short *)(pallete+index));
return Color(((s >> 12) & 0xf)*255/15,((s >> 8) & 0xf)*255/15,((s >> 4) & 0xf)*255/15 ,(s & 0xf)*255/15);
case GL_PALETTE4_RGB5_A1_OES:
case GL_PALETTE8_RGB5_A1_OES:
s = *((short *)(pallete+index));
return Color(((s >> 11) & 0x1f)*255/31,((s >> 6) & 0x1f)*255/31,((s >> 1) & 0x1f)*255/31 ,(s & 0x1) * 255);
default:
return Color(255,255,255,255);
}
}
unsigned char* uncompressTexture(GLenum internalformat,GLenum& formatOut,GLsizei width,GLsizei height,GLsizei imageSize, const GLvoid* data,GLint level) {
unsigned int indexSizeBits; //the size of the color index in the pallete
unsigned int colorSizeBytes; //the size of each color cell in the pallete
getPaletteInfo(internalformat,indexSizeBits,colorSizeBytes,formatOut);
if(!data)
{
return NULL;
}
const unsigned char* palette = static_cast<const unsigned char *>(data);
//the pallete positioned in the begininng of the data
// so we jump over it to get to the colos indices in the palette
int nColors = 2 << (indexSizeBits -1); //2^indexSizeBits
int paletteSizeBytes = nColors*colorSizeBytes;
const unsigned char* imageIndices = palette + paletteSizeBytes;
//jumping to the the correct mipmap level
for(int i=0;i<level;i++) {
imageIndices+= (width*height*indexSizeBits)/8;
width = width >> 1;
height = height >> 1;
}
int colorSizeOut = (formatOut == GL_RGB? 3:4);
int nPixels = width*height;
unsigned char* pixelsOut = new unsigned char[nPixels*colorSizeOut];
if(!pixelsOut) return NULL;
int leftBytes = ((palette + imageSize) /* the end of data pointer*/
- imageIndices);
int leftPixels = (leftBytes * 8 )/indexSizeBits;
int maxIndices = (leftPixels < nPixels) ? leftPixels:nPixels;
//filling the pixels array
for(int i =0 ; i < maxIndices ; i++) {
int paletteIndex = 0;
int indexOut = i*colorSizeOut;
if(indexSizeBits == 4) {
paletteIndex = (i%2) == 0 ?
imageIndices[i/2] >> 4: //upper bits
imageIndices[i/2] & 0xf; //lower bits
} else {
paletteIndex = imageIndices[i];
}
paletteIndex*=colorSizeBytes;
Color c = paletteColor(palette,paletteIndex,internalformat);
pixelsOut[indexOut] = c.red;
pixelsOut[indexOut+1] = c.green;
pixelsOut[indexOut+2] = c.blue;
if(formatOut == GL_RGBA) {
pixelsOut[indexOut+3] = c.alpha;
}
}
return pixelsOut;
}

View file

@ -0,0 +1,127 @@
/*
* 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 <GLcommon/RangeManip.h>
bool Range::rangeIntersection(const Range& r,Range& rOut) const {
if(m_start > r.getEnd() || r.getStart() > m_end) return false;
int max_start = (m_start > r.getStart())? m_start:r.getStart();
int min_end = (m_end < r.getEnd())?m_end:r.getEnd();
int size = min_end - max_start;
if(size) {
rOut.setRange(max_start,min_end-max_start);
return true;
}
return false;
}
bool Range::rangeUnion(const Range& r,Range& rOut) const {
if(m_start > r.getEnd() || r.getStart() > m_end) return false;
int min_start = (m_start < r.getStart())?m_start:r.getStart();
int max_end = (m_end > r.getEnd())?m_end:r.getEnd();
int size = max_end - min_start;
if(size) {
rOut.setRange(min_start,max_end-min_start);
return true;
}
return false;
}
void RangeList::addRange(const Range& r) {
if(r.getSize())
list.push_back(r);
}
void RangeList::addRanges(const RangeList& rl) {
for(int i =0; i< rl.size();i++) {
addRange(rl.list[i]);
}
}
void RangeList::delRanges(const RangeList& rl,RangeList& deleted) {
for(int i =0; i< rl.size();i++) {
delRange(rl.list[i],deleted);
}
}
bool RangeList::empty() const{
return list.empty();
}
int RangeList::size() const{
return list.size();
}
void RangeList::clear() {
return list.clear();
}
void RangeList::erase(unsigned int i) {
if(i > list.size()) return;
list.erase(list.begin() +i);
}
void RangeList::delRange(const Range& r,RangeList& deleted) {
if(r.getSize() == 0) return;
Range intersection;
Range temp;
// compare new rect to each and any of the rects on the list
for (int i=0;i<(int)list.size();i++) { // i must be signed for i-- below
// if there is intersection
if (r.rangeIntersection(list[i],intersection)) {
Range old=list[i];
// remove old as it is about to be split
erase(i);
i--;
if (intersection!=old) { // otherwise split:
//intersection on right side
if(old.getStart() != intersection.getStart()) {
list.insert(list.begin(),Range(old.getStart(),intersection.getStart() - old.getStart()));
}
//intersection on left side
if(old.getEnd() != intersection.getEnd()) {
list.insert(list.begin(),Range(intersection.getEnd(),old.getEnd() - intersection.getEnd()));
}
}
deleted.addRange(intersection);
}
}
}
void RangeList::merge() {
if(list.empty()) return;
Range temp;
bool changed;
do { // re-run if changed in last run
changed=0;
// run for each combinations of two rects in the list
for (int i=0;i<(((int)list.size())-1) && !changed ;i++)
{
for (int j=i+1;j<(int)list.size() && !changed ;j++)
{
if (list[i].rangeUnion(list[j],temp)) {
// are them exactly one on left of the other
list[i] = temp;
erase(j);
changed=1;
}
}
}
} while (changed);
}

View file

@ -0,0 +1,109 @@
/*
* 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 <GLcommon/TextureUtils.h>
#include <GLcommon/GLESmacros.h>
#include <GLcommon/GLDispatch.h>
#include <GLcommon/GLESvalidate.h>
#include <stdio.h>
#include <cmath>
int getCompressedFormats(int* formats){
if(formats){
//Palette
formats[0] = GL_PALETTE4_RGBA8_OES;
formats[1] = GL_PALETTE4_RGBA4_OES;
formats[2] = GL_PALETTE8_RGBA8_OES;
formats[3] = GL_PALETTE8_RGBA4_OES;
formats[4] = GL_PALETTE4_RGB8_OES;
formats[5] = GL_PALETTE8_RGB8_OES;
formats[6] = GL_PALETTE4_RGB5_A1_OES;
formats[7] = GL_PALETTE8_RGB5_A1_OES;
formats[8] = GL_PALETTE4_R5_G6_B5_OES;
formats[9] = GL_PALETTE8_R5_G6_B5_OES;
//ETC
formats[MAX_SUPPORTED_PALETTE] = GL_ETC1_RGB8_OES;
}
return MAX_SUPPORTED_PALETTE + MAX_ETC_SUPPORTED;
}
void doCompressedTexImage2D(GLEScontext * ctx, GLenum target, GLint level,
GLenum internalformat, GLsizei width,
GLsizei height, GLint border,
GLsizei imageSize, const GLvoid* data, void * funcPtr)
{
/* XXX: This is just a hack to fix the resolve of glTexImage2D problem
It will be removed when we'll no longer link against ligGL */
typedef void (GLAPIENTRY *glTexImage2DPtr_t ) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
glTexImage2DPtr_t glTexImage2DPtr;
glTexImage2DPtr = (glTexImage2DPtr_t)funcPtr;
switch (internalformat) {
case GL_ETC1_RGB8_OES:
{
GLint format = GL_RGB;
GLint type = GL_UNSIGNED_BYTE;
GLsizei compressedSize = etc1_get_encoded_data_size(width, height);
SET_ERROR_IF((compressedSize > imageSize), GL_INVALID_VALUE);
const int32_t align = ctx->getUnpackAlignment()-1;
const int32_t bpr = ((width * 3) + align) & ~align;
const size_t size = bpr * height;
etc1_byte* pOut = new etc1_byte[size];
int res = etc1_decode_image((const etc1_byte*)data, pOut, width, height, 3, bpr);
SET_ERROR_IF(res!=0, GL_INVALID_VALUE);
glTexImage2DPtr(target,level,format,width,height,border,format,type,pOut);
delete [] pOut;
}
break;
case GL_PALETTE4_RGB8_OES:
case GL_PALETTE4_RGBA8_OES:
case GL_PALETTE4_R5_G6_B5_OES:
case GL_PALETTE4_RGBA4_OES:
case GL_PALETTE4_RGB5_A1_OES:
case GL_PALETTE8_RGB8_OES:
case GL_PALETTE8_RGBA8_OES:
case GL_PALETTE8_R5_G6_B5_OES:
case GL_PALETTE8_RGBA4_OES:
case GL_PALETTE8_RGB5_A1_OES:
{
SET_ERROR_IF(level > log2(ctx->getMaxTexSize()) ||
border !=0 || level > 0 ||
!GLESvalidate::texImgDim(width,height,ctx->getMaxTexSize()+2),GL_INVALID_VALUE)
int nMipmaps = -level + 1;
GLsizei tmpWidth = width;
GLsizei tmpHeight = height;
for(int i = 0; i < nMipmaps ; i++)
{
GLenum uncompressedFrmt;
unsigned char* uncompressed = uncompressTexture(internalformat,uncompressedFrmt,width,height,imageSize,data,i);
glTexImage2DPtr(target,i,uncompressedFrmt,tmpWidth,tmpHeight,border,uncompressedFrmt,GL_UNSIGNED_BYTE,uncompressed);
tmpWidth/=2;
tmpHeight/=2;
delete[] uncompressed;
}
}
break;
default:
SET_ERROR_IF(1, GL_INVALID_ENUM);
break;
}
}

View file

@ -0,0 +1,670 @@
// Copyright 2009 Google Inc.
//
// 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 <ETC1/etc1.h>
#include <string.h>
/* From http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
The number of bits that represent a 4x4 texel block is 64 bits if
<internalformat> is given by ETC1_RGB8_OES.
The data for a block is a number of bytes,
{q0, q1, q2, q3, q4, q5, q6, q7}
where byte q0 is located at the lowest memory address and q7 at
the highest. The 64 bits specifying the block is then represented
by the following 64 bit integer:
int64bit = 256*(256*(256*(256*(256*(256*(256*q0+q1)+q2)+q3)+q4)+q5)+q6)+q7;
ETC1_RGB8_OES:
a) bit layout in bits 63 through 32 if diffbit = 0
63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48
-----------------------------------------------
| base col1 | base col2 | base col1 | base col2 |
| R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)|
-----------------------------------------------
47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
---------------------------------------------------
| base col1 | base col2 | table | table |diff|flip|
| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
---------------------------------------------------
b) bit layout in bits 63 through 32 if diffbit = 1
63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48
-----------------------------------------------
| base col1 | dcol 2 | base col1 | dcol 2 |
| R1' (5 bits) | dR2 | G1' (5 bits) | dG2 |
-----------------------------------------------
47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
---------------------------------------------------
| base col 1 | dcol 2 | table | table |diff|flip|
| B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
---------------------------------------------------
c) bit layout in bits 31 through 0 (in both cases)
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
-----------------------------------------------
| most significant pixel index bits |
| p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a|
-----------------------------------------------
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
--------------------------------------------------
| least significant pixel index bits |
| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
--------------------------------------------------
Add table 3.17.2: Intensity modifier sets for ETC1 compressed textures:
table codeword modifier table
------------------ ----------------------
0 -8 -2 2 8
1 -17 -5 5 17
2 -29 -9 9 29
3 -42 -13 13 42
4 -60 -18 18 60
5 -80 -24 24 80
6 -106 -33 33 106
7 -183 -47 47 183
Add table 3.17.3 Mapping from pixel index values to modifier values for
ETC1 compressed textures:
pixel index value
---------------
msb lsb resulting modifier value
----- ----- -------------------------
1 1 -b (large negative value)
1 0 -a (small negative value)
0 0 a (small positive value)
0 1 b (large positive value)
*/
static const int kModifierTable[] = {
/* 0 */2, 8, -2, -8,
/* 1 */5, 17, -5, -17,
/* 2 */9, 29, -9, -29,
/* 3 */13, 42, -13, -42,
/* 4 */18, 60, -18, -60,
/* 5 */24, 80, -24, -80,
/* 6 */33, 106, -33, -106,
/* 7 */47, 183, -47, -183 };
static const int kLookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
static inline etc1_byte clamp(int x) {
return (etc1_byte) (x >= 0 ? (x < 255 ? x : 255) : 0);
}
static
inline int convert4To8(int b) {
int c = b & 0xf;
return (c << 4) | c;
}
static
inline int convert5To8(int b) {
int c = b & 0x1f;
return (c << 3) | (c >> 2);
}
static
inline int convert6To8(int b) {
int c = b & 0x3f;
return (c << 2) | (c >> 4);
}
static
inline int divideBy255(int d) {
return (d + 128 + (d >> 8)) >> 8;
}
static
inline int convert8To4(int b) {
int c = b & 0xff;
return divideBy255(c * 15);
}
static
inline int convert8To5(int b) {
int c = b & 0xff;
return divideBy255(c * 31);
}
static
inline int convertDiff(int base, int diff) {
return convert5To8((0x1f & base) + kLookup[0x7 & diff]);
}
static
void decode_subblock(etc1_byte* pOut, int r, int g, int b, const int* table,
etc1_uint32 low, bool second, bool flipped) {
int baseX = 0;
int baseY = 0;
if (second) {
if (flipped) {
baseY = 2;
} else {
baseX = 2;
}
}
for (int i = 0; i < 8; i++) {
int x, y;
if (flipped) {
x = baseX + (i >> 1);
y = baseY + (i & 1);
} else {
x = baseX + (i >> 2);
y = baseY + (i & 3);
}
int k = y + (x * 4);
int offset = ((low >> k) & 1) | ((low >> (k + 15)) & 2);
int delta = table[offset];
etc1_byte* q = pOut + 3 * (x + 4 * y);
*q++ = clamp(r + delta);
*q++ = clamp(g + delta);
*q++ = clamp(b + delta);
}
}
// Input is an ETC1 compressed version of the data.
// Output is a 4 x 4 square of 3-byte pixels in form R, G, B
void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut) {
etc1_uint32 high = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
etc1_uint32 low = (pIn[4] << 24) | (pIn[5] << 16) | (pIn[6] << 8) | pIn[7];
int r1, r2, g1, g2, b1, b2;
if (high & 2) {
// differential
int rBase = high >> 27;
int gBase = high >> 19;
int bBase = high >> 11;
r1 = convert5To8(rBase);
r2 = convertDiff(rBase, high >> 24);
g1 = convert5To8(gBase);
g2 = convertDiff(gBase, high >> 16);
b1 = convert5To8(bBase);
b2 = convertDiff(bBase, high >> 8);
} else {
// not differential
r1 = convert4To8(high >> 28);
r2 = convert4To8(high >> 24);
g1 = convert4To8(high >> 20);
g2 = convert4To8(high >> 16);
b1 = convert4To8(high >> 12);
b2 = convert4To8(high >> 8);
}
int tableIndexA = 7 & (high >> 5);
int tableIndexB = 7 & (high >> 2);
const int* tableA = kModifierTable + tableIndexA * 4;
const int* tableB = kModifierTable + tableIndexB * 4;
bool flipped = (high & 1) != 0;
decode_subblock(pOut, r1, g1, b1, tableA, low, false, flipped);
decode_subblock(pOut, r2, g2, b2, tableB, low, true, flipped);
}
typedef struct {
etc1_uint32 high;
etc1_uint32 low;
etc1_uint32 score; // Lower is more accurate
} etc_compressed;
static
inline void take_best(etc_compressed* a, const etc_compressed* b) {
if (a->score > b->score) {
*a = *b;
}
}
static
void etc_average_colors_subblock(const etc1_byte* pIn, etc1_uint32 inMask,
etc1_byte* pColors, bool flipped, bool second) {
int r = 0;
int g = 0;
int b = 0;
if (flipped) {
int by = 0;
if (second) {
by = 2;
}
for (int y = 0; y < 2; y++) {
int yy = by + y;
for (int x = 0; x < 4; x++) {
int i = x + 4 * yy;
if (inMask & (1 << i)) {
const etc1_byte* p = pIn + i * 3;
r += *(p++);
g += *(p++);
b += *(p++);
}
}
}
} else {
int bx = 0;
if (second) {
bx = 2;
}
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 2; x++) {
int xx = bx + x;
int i = xx + 4 * y;
if (inMask & (1 << i)) {
const etc1_byte* p = pIn + i * 3;
r += *(p++);
g += *(p++);
b += *(p++);
}
}
}
}
pColors[0] = (etc1_byte)((r + 4) >> 3);
pColors[1] = (etc1_byte)((g + 4) >> 3);
pColors[2] = (etc1_byte)((b + 4) >> 3);
}
static
inline int square(int x) {
return x * x;
}
static etc1_uint32 chooseModifier(const etc1_byte* pBaseColors,
const etc1_byte* pIn, etc1_uint32 *pLow, int bitIndex,
const int* pModifierTable) {
etc1_uint32 bestScore = ~0;
int bestIndex = 0;
int pixelR = pIn[0];
int pixelG = pIn[1];
int pixelB = pIn[2];
int r = pBaseColors[0];
int g = pBaseColors[1];
int b = pBaseColors[2];
for (int i = 0; i < 4; i++) {
int modifier = pModifierTable[i];
int decodedG = clamp(g + modifier);
etc1_uint32 score = (etc1_uint32) (6 * square(decodedG - pixelG));
if (score >= bestScore) {
continue;
}
int decodedR = clamp(r + modifier);
score += (etc1_uint32) (3 * square(decodedR - pixelR));
if (score >= bestScore) {
continue;
}
int decodedB = clamp(b + modifier);
score += (etc1_uint32) square(decodedB - pixelB);
if (score < bestScore) {
bestScore = score;
bestIndex = i;
}
}
etc1_uint32 lowMask = (((bestIndex >> 1) << 16) | (bestIndex & 1))
<< bitIndex;
*pLow |= lowMask;
return bestScore;
}
static
void etc_encode_subblock_helper(const etc1_byte* pIn, etc1_uint32 inMask,
etc_compressed* pCompressed, bool flipped, bool second,
const etc1_byte* pBaseColors, const int* pModifierTable) {
int score = pCompressed->score;
if (flipped) {
int by = 0;
if (second) {
by = 2;
}
for (int y = 0; y < 2; y++) {
int yy = by + y;
for (int x = 0; x < 4; x++) {
int i = x + 4 * yy;
if (inMask & (1 << i)) {
score += chooseModifier(pBaseColors, pIn + i * 3,
&pCompressed->low, yy + x * 4, pModifierTable);
}
}
}
} else {
int bx = 0;
if (second) {
bx = 2;
}
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 2; x++) {
int xx = bx + x;
int i = xx + 4 * y;
if (inMask & (1 << i)) {
score += chooseModifier(pBaseColors, pIn + i * 3,
&pCompressed->low, y + xx * 4, pModifierTable);
}
}
}
}
pCompressed->score = score;
}
static bool inRange4bitSigned(int color) {
return color >= -4 && color <= 3;
}
static void etc_encodeBaseColors(etc1_byte* pBaseColors,
const etc1_byte* pColors, etc_compressed* pCompressed) {
int r1, g1, b1, r2, g2, b2; // 8 bit base colors for sub-blocks
bool differential;
{
int r51 = convert8To5(pColors[0]);
int g51 = convert8To5(pColors[1]);
int b51 = convert8To5(pColors[2]);
int r52 = convert8To5(pColors[3]);
int g52 = convert8To5(pColors[4]);
int b52 = convert8To5(pColors[5]);
r1 = convert5To8(r51);
g1 = convert5To8(g51);
b1 = convert5To8(b51);
int dr = r52 - r51;
int dg = g52 - g51;
int db = b52 - b51;
differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
&& inRange4bitSigned(db);
if (differential) {
r2 = convert5To8(r51 + dr);
g2 = convert5To8(g51 + dg);
b2 = convert5To8(b51 + db);
pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
| ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
}
}
if (!differential) {
int r41 = convert8To4(pColors[0]);
int g41 = convert8To4(pColors[1]);
int b41 = convert8To4(pColors[2]);
int r42 = convert8To4(pColors[3]);
int g42 = convert8To4(pColors[4]);
int b42 = convert8To4(pColors[5]);
r1 = convert4To8(r41);
g1 = convert4To8(g41);
b1 = convert4To8(b41);
r2 = convert4To8(r42);
g2 = convert4To8(g42);
b2 = convert4To8(b42);
pCompressed->high |= (r41 << 28) | (r42 << 24) | (g41 << 20) | (g42
<< 16) | (b41 << 12) | (b42 << 8);
}
pBaseColors[0] = r1;
pBaseColors[1] = g1;
pBaseColors[2] = b1;
pBaseColors[3] = r2;
pBaseColors[4] = g2;
pBaseColors[5] = b2;
}
static
void etc_encode_block_helper(const etc1_byte* pIn, etc1_uint32 inMask,
const etc1_byte* pColors, etc_compressed* pCompressed, bool flipped) {
pCompressed->score = ~0;
pCompressed->high = (flipped ? 1 : 0);
pCompressed->low = 0;
etc1_byte pBaseColors[6];
etc_encodeBaseColors(pBaseColors, pColors, pCompressed);
int originalHigh = pCompressed->high;
const int* pModifierTable = kModifierTable;
for (int i = 0; i < 8; i++, pModifierTable += 4) {
etc_compressed temp;
temp.score = 0;
temp.high = originalHigh | (i << 5);
temp.low = 0;
etc_encode_subblock_helper(pIn, inMask, &temp, flipped, false,
pBaseColors, pModifierTable);
take_best(pCompressed, &temp);
}
pModifierTable = kModifierTable;
etc_compressed firstHalf = *pCompressed;
for (int i = 0; i < 8; i++, pModifierTable += 4) {
etc_compressed temp;
temp.score = firstHalf.score;
temp.high = firstHalf.high | (i << 2);
temp.low = firstHalf.low;
etc_encode_subblock_helper(pIn, inMask, &temp, flipped, true,
pBaseColors + 3, pModifierTable);
if (i == 0) {
*pCompressed = temp;
} else {
take_best(pCompressed, &temp);
}
}
}
static void writeBigEndian(etc1_byte* pOut, etc1_uint32 d) {
pOut[0] = (etc1_byte)(d >> 24);
pOut[1] = (etc1_byte)(d >> 16);
pOut[2] = (etc1_byte)(d >> 8);
pOut[3] = (etc1_byte) d;
}
// Input is a 4 x 4 square of 3-byte pixels in form R, G, B
// inmask is a 16-bit mask where bit (1 << (x + y * 4)) tells whether the corresponding (x,y)
// pixel is valid or not. Invalid pixel color values are ignored when compressing.
// Output is an ETC1 compressed version of the data.
void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 inMask,
etc1_byte* pOut) {
etc1_byte colors[6];
etc1_byte flippedColors[6];
etc_average_colors_subblock(pIn, inMask, colors, false, false);
etc_average_colors_subblock(pIn, inMask, colors + 3, false, true);
etc_average_colors_subblock(pIn, inMask, flippedColors, true, false);
etc_average_colors_subblock(pIn, inMask, flippedColors + 3, true, true);
etc_compressed a, b;
etc_encode_block_helper(pIn, inMask, colors, &a, false);
etc_encode_block_helper(pIn, inMask, flippedColors, &b, true);
take_best(&a, &b);
writeBigEndian(pOut, a.high);
writeBigEndian(pOut + 4, a.low);
}
// Return the size of the encoded image data (does not include size of PKM header).
etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height) {
return (((width + 3) & ~3) * ((height + 3) & ~3)) >> 1;
}
// Encode an entire image.
// pIn - pointer to the image data. Formatted such that the Red component of
// pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset;
// pOut - pointer to encoded data. Must be large enough to store entire encoded image.
int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height,
etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut) {
if (pixelSize < 2 || pixelSize > 3) {
return -1;
}
static const unsigned short kYMask[] = { 0x0, 0xf, 0xff, 0xfff, 0xffff };
static const unsigned short kXMask[] = { 0x0, 0x1111, 0x3333, 0x7777,
0xffff };
etc1_byte block[ETC1_DECODED_BLOCK_SIZE];
etc1_byte encoded[ETC1_ENCODED_BLOCK_SIZE];
etc1_uint32 encodedWidth = (width + 3) & ~3;
etc1_uint32 encodedHeight = (height + 3) & ~3;
for (etc1_uint32 y = 0; y < encodedHeight; y += 4) {
etc1_uint32 yEnd = height - y;
if (yEnd > 4) {
yEnd = 4;
}
int ymask = kYMask[yEnd];
for (etc1_uint32 x = 0; x < encodedWidth; x += 4) {
etc1_uint32 xEnd = width - x;
if (xEnd > 4) {
xEnd = 4;
}
int mask = ymask & kXMask[xEnd];
for (etc1_uint32 cy = 0; cy < yEnd; cy++) {
etc1_byte* q = block + (cy * 4) * 3;
const etc1_byte* p = pIn + pixelSize * x + stride * (y + cy);
if (pixelSize == 3) {
memcpy(q, p, xEnd * 3);
} else {
for (etc1_uint32 cx = 0; cx < xEnd; cx++) {
int pixel = (p[1] << 8) | p[0];
*q++ = convert5To8(pixel >> 11);
*q++ = convert6To8(pixel >> 5);
*q++ = convert5To8(pixel);
p += pixelSize;
}
}
}
etc1_encode_block(block, mask, encoded);
memcpy(pOut, encoded, sizeof(encoded));
pOut += sizeof(encoded);
}
}
return 0;
}
// Decode an entire image.
// pIn - pointer to encoded data.
// pOut - pointer to the image data. Will be written such that the Red component of
// pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset. Must be
// large enough to store entire image.
int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut,
etc1_uint32 width, etc1_uint32 height,
etc1_uint32 pixelSize, etc1_uint32 stride) {
if (pixelSize < 2 || pixelSize > 3) {
return -1;
}
etc1_byte block[ETC1_DECODED_BLOCK_SIZE];
etc1_uint32 encodedWidth = (width + 3) & ~3;
etc1_uint32 encodedHeight = (height + 3) & ~3;
for (etc1_uint32 y = 0; y < encodedHeight; y += 4) {
etc1_uint32 yEnd = height - y;
if (yEnd > 4) {
yEnd = 4;
}
for (etc1_uint32 x = 0; x < encodedWidth; x += 4) {
etc1_uint32 xEnd = width - x;
if (xEnd > 4) {
xEnd = 4;
}
etc1_decode_block(pIn, block);
pIn += ETC1_ENCODED_BLOCK_SIZE;
for (etc1_uint32 cy = 0; cy < yEnd; cy++) {
const etc1_byte* q = block + (cy * 4) * 3;
etc1_byte* p = pOut + pixelSize * x + stride * (y + cy);
if (pixelSize == 3) {
memcpy(p, q, xEnd * 3);
} else {
for (etc1_uint32 cx = 0; cx < xEnd; cx++) {
etc1_byte r = *q++;
etc1_byte g = *q++;
etc1_byte b = *q++;
etc1_uint32 pixel = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
*p++ = (etc1_byte) pixel;
*p++ = (etc1_byte) (pixel >> 8);
}
}
}
}
}
return 0;
}
static const char kMagic[] = { 'P', 'K', 'M', ' ', '1', '0' };
static const etc1_uint32 ETC1_PKM_FORMAT_OFFSET = 6;
static const etc1_uint32 ETC1_PKM_ENCODED_WIDTH_OFFSET = 8;
static const etc1_uint32 ETC1_PKM_ENCODED_HEIGHT_OFFSET = 10;
static const etc1_uint32 ETC1_PKM_WIDTH_OFFSET = 12;
static const etc1_uint32 ETC1_PKM_HEIGHT_OFFSET = 14;
static const etc1_uint32 ETC1_RGB_NO_MIPMAPS = 0;
static void writeBEUint16(etc1_byte* pOut, etc1_uint32 data) {
pOut[0] = (etc1_byte) (data >> 8);
pOut[1] = (etc1_byte) data;
}
static etc1_uint32 readBEUint16(const etc1_byte* pIn) {
return (pIn[0] << 8) | pIn[1];
}
// Format a PKM header
void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height) {
memcpy(pHeader, kMagic, sizeof(kMagic));
etc1_uint32 encodedWidth = (width + 3) & ~3;
etc1_uint32 encodedHeight = (height + 3) & ~3;
writeBEUint16(pHeader + ETC1_PKM_FORMAT_OFFSET, ETC1_RGB_NO_MIPMAPS);
writeBEUint16(pHeader + ETC1_PKM_ENCODED_WIDTH_OFFSET, encodedWidth);
writeBEUint16(pHeader + ETC1_PKM_ENCODED_HEIGHT_OFFSET, encodedHeight);
writeBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET, width);
writeBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET, height);
}
// Check if a PKM header is correctly formatted.
etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader) {
if (memcmp(pHeader, kMagic, sizeof(kMagic))) {
return false;
}
etc1_uint32 format = readBEUint16(pHeader + ETC1_PKM_FORMAT_OFFSET);
etc1_uint32 encodedWidth = readBEUint16(pHeader + ETC1_PKM_ENCODED_WIDTH_OFFSET);
etc1_uint32 encodedHeight = readBEUint16(pHeader + ETC1_PKM_ENCODED_HEIGHT_OFFSET);
etc1_uint32 width = readBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET);
etc1_uint32 height = readBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET);
return format == ETC1_RGB_NO_MIPMAPS &&
encodedWidth >= width && encodedWidth - width < 4 &&
encodedHeight >= height && encodedHeight - height < 4;
}
// Read the image width from a PKM header
etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader) {
return readBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET);
}
// Read the image height from a PKM header
etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader){
return readBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET);
}

View file

@ -0,0 +1,369 @@
/*
* 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 <map>
#include <GLcommon/objectNameManager.h>
#include <GLcommon/GLEScontext.h>
NameSpace::NameSpace(NamedObjectType p_type,
GlobalNameSpace *globalNameSpace) :
m_nextName(0),
m_type(p_type),
m_globalNameSpace(globalNameSpace) {}
NameSpace::~NameSpace()
{
for (NamesMap::iterator n = m_localToGlobalMap.begin();
n != m_localToGlobalMap.end();
n++) {
m_globalNameSpace->deleteName(m_type, (*n).second);
}
}
ObjectLocalName
NameSpace::genName(ObjectLocalName p_localName,
bool genGlobal, bool genLocal)
{
ObjectLocalName localName = p_localName;
if (genLocal) {
do {
localName = ++m_nextName;
} while(localName == 0 ||
m_localToGlobalMap.find(localName) !=
m_localToGlobalMap.end() );
}
if (genGlobal) {
unsigned int globalName = m_globalNameSpace->genName(m_type);
m_localToGlobalMap[localName] = globalName;
}
return localName;
}
unsigned int
NameSpace::genGlobalName(void)
{
return m_globalNameSpace->genName(m_type);
}
unsigned int
NameSpace::getGlobalName(ObjectLocalName p_localName)
{
NamesMap::iterator n( m_localToGlobalMap.find(p_localName) );
if (n != m_localToGlobalMap.end()) {
// object found - return its global name map
return (*n).second;
}
// object does not exist;
return 0;
}
ObjectLocalName
NameSpace::getLocalName(unsigned int p_globalName)
{
for(NamesMap::iterator it = m_localToGlobalMap.begin(); it != m_localToGlobalMap.end();it++){
if((*it).second == p_globalName){
// object found - return its local name
return (*it).first;
}
}
// object does not exist;
return 0;
}
void
NameSpace::deleteName(ObjectLocalName p_localName)
{
NamesMap::iterator n( m_localToGlobalMap.find(p_localName) );
if (n != m_localToGlobalMap.end()) {
m_globalNameSpace->deleteName(m_type, (*n).second);
m_localToGlobalMap.erase(p_localName);
}
}
bool
NameSpace::isObject(ObjectLocalName p_localName)
{
return (m_localToGlobalMap.find(p_localName) != m_localToGlobalMap.end() );
}
void
NameSpace::replaceGlobalName(ObjectLocalName p_localName, unsigned int p_globalName)
{
NamesMap::iterator n( m_localToGlobalMap.find(p_localName) );
if (n != m_localToGlobalMap.end()) {
m_globalNameSpace->deleteName(m_type, (*n).second);
(*n).second = p_globalName;
}
}
GlobalNameSpace::GlobalNameSpace() : m_lock() {}
GlobalNameSpace::~GlobalNameSpace() {}
unsigned int
GlobalNameSpace::genName(NamedObjectType p_type)
{
if ( p_type >= NUM_OBJECT_TYPES ) return 0;
unsigned int name = 0;
emugl::Mutex::AutoLock _lock(m_lock);
switch (p_type) {
case VERTEXBUFFER:
GLEScontext::dispatcher().glGenBuffers(1,&name);
break;
case TEXTURE:
GLEScontext::dispatcher().glGenTextures(1,&name);
break;
case RENDERBUFFER:
GLEScontext::dispatcher().glGenRenderbuffersEXT(1,&name);
break;
case FRAMEBUFFER:
GLEScontext::dispatcher().glGenFramebuffersEXT(1,&name);
break;
case SHADER: //objects in shader namepace are not handled
default:
name = 0;
}
return name;
}
void
GlobalNameSpace::deleteName(NamedObjectType p_type, unsigned int p_name)
{
}
typedef std::pair<NamedObjectType, ObjectLocalName> ObjectIDPair;
typedef std::map<ObjectIDPair, ObjectDataPtr> ObjectDataMap;
ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace) : m_lock() {
for (int i=0; i < NUM_OBJECT_TYPES; i++) {
m_nameSpace[i] = new NameSpace((NamedObjectType)i, globalNameSpace);
}
m_objectsData = NULL;
}
ShareGroup::~ShareGroup()
{
emugl::Mutex::AutoLock _lock(m_lock);
for (int t = 0; t < NUM_OBJECT_TYPES; t++) {
delete m_nameSpace[t];
}
delete (ObjectDataMap *)m_objectsData;
}
ObjectLocalName
ShareGroup::genName(NamedObjectType p_type,
ObjectLocalName p_localName,
bool genLocal)
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
emugl::Mutex::AutoLock _lock(m_lock);
ObjectLocalName localName =
m_nameSpace[p_type]->genName(p_localName, true, genLocal);
return localName;
}
unsigned int
ShareGroup::genGlobalName(NamedObjectType p_type)
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
emugl::Mutex::AutoLock _lock(m_lock);
return m_nameSpace[p_type]->genGlobalName();
}
unsigned int
ShareGroup::getGlobalName(NamedObjectType p_type,
ObjectLocalName p_localName)
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
emugl::Mutex::AutoLock _lock(m_lock);
return m_nameSpace[p_type]->getGlobalName(p_localName);
}
ObjectLocalName
ShareGroup::getLocalName(NamedObjectType p_type,
unsigned int p_globalName)
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
emugl::Mutex::AutoLock _lock(m_lock);
return m_nameSpace[p_type]->getLocalName(p_globalName);
}
void
ShareGroup::deleteName(NamedObjectType p_type, ObjectLocalName p_localName)
{
if (p_type >= NUM_OBJECT_TYPES) return;
emugl::Mutex::AutoLock _lock(m_lock);
m_nameSpace[p_type]->deleteName(p_localName);
ObjectDataMap *map = (ObjectDataMap *)m_objectsData;
if (map) {
map->erase( ObjectIDPair(p_type, p_localName) );
}
}
bool
ShareGroup::isObject(NamedObjectType p_type, ObjectLocalName p_localName)
{
if (p_type >= NUM_OBJECT_TYPES) return 0;
emugl::Mutex::AutoLock _lock(m_lock);
return m_nameSpace[p_type]->isObject(p_localName);
}
void
ShareGroup::replaceGlobalName(NamedObjectType p_type,
ObjectLocalName p_localName,
unsigned int p_globalName)
{
if (p_type >= NUM_OBJECT_TYPES) return;
emugl::Mutex::AutoLock _lock(m_lock);
m_nameSpace[p_type]->replaceGlobalName(p_localName, p_globalName);
}
void
ShareGroup::setObjectData(NamedObjectType p_type,
ObjectLocalName p_localName,
ObjectDataPtr data)
{
if (p_type >= NUM_OBJECT_TYPES) return;
emugl::Mutex::AutoLock _lock(m_lock);
ObjectDataMap *map = (ObjectDataMap *)m_objectsData;
if (!map) {
map = new ObjectDataMap();
m_objectsData = map;
}
ObjectIDPair id( p_type, p_localName );
map->insert( std::pair<ObjectIDPair, ObjectDataPtr>(id, data) );
}
ObjectDataPtr
ShareGroup::getObjectData(NamedObjectType p_type,
ObjectLocalName p_localName)
{
ObjectDataPtr ret;
if (p_type >= NUM_OBJECT_TYPES) return ret;
emugl::Mutex::AutoLock _lock(m_lock);
ObjectDataMap *map = (ObjectDataMap *)m_objectsData;
if (map) {
ObjectDataMap::iterator i =
map->find( ObjectIDPair(p_type, p_localName) );
if (i != map->end()) ret = (*i).second;
}
return ret;
}
ObjectNameManager::ObjectNameManager(GlobalNameSpace *globalNameSpace) :
m_lock(), m_globalNameSpace(globalNameSpace) {}
ObjectNameManager::~ObjectNameManager() {}
ShareGroupPtr
ObjectNameManager::createShareGroup(void *p_groupName)
{
emugl::Mutex::AutoLock _lock(m_lock);
ShareGroupPtr shareGroupReturn;
ShareGroupsMap::iterator s( m_groups.find(p_groupName) );
if (s != m_groups.end()) {
shareGroupReturn = (*s).second;
}
else {
//
// Group does not exist, create new group
//
shareGroupReturn = ShareGroupPtr(new ShareGroup(m_globalNameSpace));
m_groups.insert(
std::pair<void*, ShareGroupPtr>(
p_groupName, shareGroupReturn));
}
return shareGroupReturn;
}
ShareGroupPtr
ObjectNameManager::getShareGroup(void *p_groupName)
{
emugl::Mutex::AutoLock _lock(m_lock);
ShareGroupPtr shareGroupReturn(NULL);
ShareGroupsMap::iterator s( m_groups.find(p_groupName) );
if (s != m_groups.end()) {
shareGroupReturn = (*s).second;
}
return shareGroupReturn;
}
ShareGroupPtr
ObjectNameManager::attachShareGroup(void *p_groupName,
void *p_existingGroupName)
{
emugl::Mutex::AutoLock _lock(m_lock);
ShareGroupsMap::iterator s( m_groups.find(p_existingGroupName) );
if (s == m_groups.end()) {
// ShareGroup did not found !!!
return ShareGroupPtr(NULL);
}
ShareGroupPtr shareGroupReturn((*s).second);
if (m_groups.find(p_groupName) == m_groups.end()) {
m_groups.insert(
std::pair<void*, ShareGroupPtr>(
p_groupName, shareGroupReturn));
}
return shareGroupReturn;
}
void
ObjectNameManager::deleteShareGroup(void *p_groupName)
{
emugl::Mutex::AutoLock _lock(m_lock);
ShareGroupsMap::iterator s( m_groups.find(p_groupName) );
if (s != m_groups.end()) {
m_groups.erase(s);
}
}
void *ObjectNameManager::getGlobalContext()
{
emugl::Mutex::AutoLock _lock(m_lock);
return (m_groups.size() > 0) ? (*m_groups.begin()).first : NULL;
}

View file

@ -0,0 +1,72 @@
/*
* 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.
*/
#ifndef _FRAMEBUFFER_DATA_H
#define _FRAMEBUFFER_DATA_H
#include "objectNameManager.h"
#include <GLES/gl.h>
#include <GLES/glext.h>
class RenderbufferData : public ObjectData
{
public:
RenderbufferData();
~RenderbufferData();
unsigned int sourceEGLImage;
void (*eglImageDetach)(unsigned int imageId);
GLuint attachedFB;
GLenum attachedPoint;
GLuint eglImageGlobalTexName;
};
const int MAX_ATTACH_POINTS = 3;
class FramebufferData : public ObjectData
{
public:
explicit FramebufferData(GLuint name);
~FramebufferData();
void setAttachment(GLenum attachment,
GLenum target,
GLuint name,
ObjectDataPtr obj,
bool takeOwnership = false);
GLuint getAttachment(GLenum attachment,
GLenum *outTarget,
ObjectDataPtr *outObj);
void validate(class GLEScontext* ctx);
private:
inline int attachmentPointIndex(GLenum attachment);
void detachObject(int idx);
private:
GLuint m_fbName;
struct attachPoint {
GLenum target; // OGL if owned, GLES otherwise
GLuint name; // OGL if owned, GLES otherwise
ObjectDataPtr obj;
bool owned;
} m_attachPoints[MAX_ATTACH_POINTS+1];
bool m_dirty;
};
#endif

View file

@ -0,0 +1,50 @@
/*
* 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.
*/
#ifndef GL_DISPATCHH
#define GL_DISPATCHH
#include <GLES/gl.h>
#include <GLES2/gl2.h>
#include "OpenGLESDispatch/gldefs.h"
#include "OpenGLESDispatch/gles_functions.h"
#include "GLutils.h"
#include "emugl/common/mutex.h"
#define GLAPIENTRY GL_APIENTRY
typedef void(*FUNCPTR)();
class GlLibrary;
#define GLES_DECLARE_METHOD(return_type, function_name, signature, args) \
static GL_APICALL return_type (GL_APIENTRY *function_name) signature;
class GLDispatch {
public:
// Constructor.
GLDispatch();
void dispatchFuncs(GLESVersion version, GlLibrary* glLib);
LIST_GLES_FUNCTIONS(GLES_DECLARE_METHOD, GLES_DECLARE_METHOD)
private:
bool m_isLoaded;
static emugl::Mutex s_lock;
};
#endif // GL_DISPATCH_H

View file

@ -0,0 +1,47 @@
/*
* 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.
*/
#ifndef GLES_BUFFER_H
#define GLES_BUFFER_H
#include <stdio.h>
#include <GLES/gl.h>
#include <GLcommon/objectNameManager.h>
#include <GLcommon/RangeManip.h>
class GLESbuffer: public ObjectData {
public:
GLESbuffer():ObjectData(BUFFER_DATA),m_size(0),m_usage(GL_STATIC_DRAW),m_data(NULL),m_wasBound(false){}
GLuint getSize(){return m_size;};
GLuint getUsage(){return m_usage;};
GLvoid* getData(){ return m_data;}
bool setBuffer(GLuint size,GLuint usage,const GLvoid* data);
bool setSubBuffer(GLint offset,GLuint size,const GLvoid* data);
void getConversions(const RangeList& rIn,RangeList& rOut);
bool fullyConverted(){return m_conversionManager.size() == 0;};
void setBinded(){m_wasBound = true;};
bool wasBinded(){return m_wasBound;};
~GLESbuffer();
private:
GLuint m_size;
GLuint m_usage;
unsigned char* m_data;
RangeList m_conversionManager;
bool m_wasBound;
};
typedef emugl::SmartPtr<GLESbuffer> GLESbufferPtr;
#endif

View file

@ -0,0 +1,222 @@
/*
* Copyright 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.
*/
#ifndef GLES_CONTEXT_H
#define GLES_CONTEXT_H
#include "GLDispatch.h"
#include "GLESpointer.h"
#include "objectNameManager.h"
#include "emugl/common/mutex.h"
#include <string>
typedef std::map<GLenum,GLESpointer*> ArraysMap;
enum TextureTarget {
TEXTURE_2D,
TEXTURE_CUBE_MAP,
NUM_TEXTURE_TARGETS
};
typedef struct _textureTargetState {
GLuint texture;
GLboolean enabled;
} textureTargetState;
typedef textureTargetState textureUnitState[NUM_TEXTURE_TARGETS];
class Version{
public:
Version();
Version(int major,int minor,int release);
Version(const char* versionString);
Version(const Version& ver);
bool operator<(const Version& ver) const;
Version& operator=(const Version& ver);
private:
int m_major;
int m_minor;
int m_release;
};
struct GLSupport {
GLSupport():maxLights(0),maxVertexAttribs(0),maxClipPlane(0),maxTexUnits(0), \
maxTexImageUnits(0),maxTexSize(0) , maxCombinedTexImageUnits(0), \
GL_EXT_TEXTURE_FORMAT_BGRA8888(false), GL_EXT_FRAMEBUFFER_OBJECT(false), \
GL_ARB_VERTEX_BLEND(false), GL_ARB_MATRIX_PALETTE(false), \
GL_EXT_PACKED_DEPTH_STENCIL(false) , GL_OES_READ_FORMAT(false), \
GL_ARB_HALF_FLOAT_PIXEL(false), GL_NV_HALF_FLOAT(false), \
GL_ARB_HALF_FLOAT_VERTEX(false),GL_SGIS_GENERATE_MIPMAP(false),
GL_ARB_ES2_COMPATIBILITY(false),GL_OES_STANDARD_DERIVATIVES(false),
GL_OES_TEXTURE_NPOT(false), GL_OES_RGB8_RGBA8(false) {} ;
int maxLights;
int maxVertexAttribs;
int maxClipPlane;
int maxTexUnits;
int maxTexImageUnits;
int maxTexSize;
int maxCombinedTexImageUnits;
Version glslVersion;
bool GL_EXT_TEXTURE_FORMAT_BGRA8888;
bool GL_EXT_FRAMEBUFFER_OBJECT;
bool GL_ARB_VERTEX_BLEND;
bool GL_ARB_MATRIX_PALETTE;
bool GL_EXT_PACKED_DEPTH_STENCIL;
bool GL_OES_READ_FORMAT;
bool GL_ARB_HALF_FLOAT_PIXEL;
bool GL_NV_HALF_FLOAT;
bool GL_ARB_HALF_FLOAT_VERTEX;
bool GL_SGIS_GENERATE_MIPMAP;
bool GL_ARB_ES2_COMPATIBILITY;
bool GL_OES_STANDARD_DERIVATIVES;
bool GL_OES_TEXTURE_NPOT;
bool GL_OES_RGB8_RGBA8;
};
struct ArrayData{
ArrayData():data(NULL),
type(0),
stride(0),
allocated(false){};
void* data;
GLenum type;
unsigned int stride;
bool allocated;
};
class GLESConversionArrays
{
public:
GLESConversionArrays():m_current(0){};
void setArr(void* data,unsigned int stride,GLenum type);
void allocArr(unsigned int size,GLenum type);
ArrayData& operator[](int i);
void* getCurrentData();
ArrayData& getCurrentArray();
unsigned int getCurrentIndex();
void operator++();
~GLESConversionArrays();
private:
std::map<GLenum,ArrayData> m_arrays;
unsigned int m_current;
};
class GLEScontext{
public:
virtual void init(GlLibrary* glLib);
GLEScontext();
GLenum getGLerror();
void setGLerror(GLenum err);
void setShareGroup(ShareGroupPtr grp){m_shareGroup = grp;};
ShareGroupPtr shareGroup() const { return m_shareGroup; }
virtual void setActiveTexture(GLenum tex);
unsigned int getBindedTexture(GLenum target);
unsigned int getBindedTexture(GLenum unit,GLenum target);
void setBindedTexture(GLenum target,unsigned int tex);
bool isTextureUnitEnabled(GLenum unit);
void setTextureEnabled(GLenum target, GLenum enable);
ObjectLocalName getDefaultTextureName(GLenum target);
bool isInitialized() { return m_initialized; };
void setUnpackAlignment(GLint param){ m_unpackAlignment = param; };
GLint getUnpackAlignment(){ return m_unpackAlignment; };
bool isArrEnabled(GLenum);
void enableArr(GLenum arr,bool enable);
const GLvoid* setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize = false);
virtual const GLESpointer* getPointer(GLenum arrType);
virtual void setupArraysPointers(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) = 0;
void bindBuffer(GLenum target,GLuint buffer);
void unbindBuffer(GLuint buffer);
bool isBuffer(GLuint buffer);
bool isBindedBuffer(GLenum target);
GLvoid* getBindedBuffer(GLenum target);
void getBufferSize(GLenum target,GLint* param);
void getBufferUsage(GLenum target,GLint* param);
bool setBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage);
bool setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid* data);
const char * getExtensionString();
const char * getVendorString() const;
const char * getRendererString() const;
const char * getVersionString() const;
void getGlobalLock();
void releaseGlobalLock();
virtual GLSupport* getCaps(){return &s_glSupport;};
virtual ~GLEScontext();
virtual int getMaxTexUnits() = 0;
virtual void drawValidate(void);
void setRenderbufferBinding(GLuint rb) { m_renderbuffer = rb; }
GLuint getRenderbufferBinding() const { return m_renderbuffer; }
void setFramebufferBinding(GLuint fb) { m_framebuffer = fb; }
GLuint getFramebufferBinding() const { return m_framebuffer; }
static GLDispatch& dispatcher(){return s_glDispatch;};
static int getMaxLights(){return s_glSupport.maxLights;}
static int getMaxClipPlanes(){return s_glSupport.maxClipPlane;}
static int getMaxTexSize(){return s_glSupport.maxTexSize;}
static Version glslVersion(){return s_glSupport.glslVersion;}
static bool isAutoMipmapSupported(){return s_glSupport.GL_SGIS_GENERATE_MIPMAP;}
static TextureTarget GLTextureTargetToLocal(GLenum target);
static unsigned int findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices);
virtual bool glGetIntegerv(GLenum pname, GLint *params);
virtual bool glGetBooleanv(GLenum pname, GLboolean *params);
virtual bool glGetFloatv(GLenum pname, GLfloat *params);
virtual bool glGetFixedv(GLenum pname, GLfixed *params);
protected:
static void buildStrings(const char* baseVendor, const char* baseRenderer, const char* baseVersion, const char* version);
virtual bool needConvert(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) = 0;
void convertDirect(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p);
void convertDirectVBO(GLESConversionArrays& fArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p);
void convertIndirect(GLESConversionArrays& fArrs,GLsizei count,GLenum type,const GLvoid* indices,GLenum array_id,GLESpointer* p);
void convertIndirectVBO(GLESConversionArrays& fArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p);
void initCapsLocked(const GLubyte * extensionString);
virtual void initExtensionString() =0;
static emugl::Mutex s_lock;
static GLDispatch s_glDispatch;
bool m_initialized;
unsigned int m_activeTexture;
GLint m_unpackAlignment;
ArraysMap m_map;
static std::string* s_glExtensions;
static GLSupport s_glSupport;
private:
virtual void setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride, GLboolean normalized, int pointsIndex = -1) = 0 ;
GLuint getBuffer(GLenum target);
ShareGroupPtr m_shareGroup;
GLenum m_glError;
textureUnitState* m_texState;
unsigned int m_arrayBuffer;
unsigned int m_elementBuffer;
GLuint m_renderbuffer;
GLuint m_framebuffer;
static std::string s_glVendor;
static std::string s_glRenderer;
static std::string s_glVersion;
};
#endif

View file

@ -0,0 +1,48 @@
#ifndef GLES_MACROS_H
#define GLES_MACROS_H
#define GET_CTX() \
if(!s_eglIface) return; \
GLEScontext *ctx = s_eglIface->getGLESContext(); \
if(!ctx) return;
#define GET_CTX_CM() \
if(!s_eglIface) return; \
GLEScmContext *ctx = static_cast<GLEScmContext *>(s_eglIface->getGLESContext()); \
if(!ctx) return;
#define GET_CTX_V2() \
if(!s_eglIface) return; \
GLESv2Context *ctx = static_cast<GLESv2Context *>(s_eglIface->getGLESContext()); \
if(!ctx) return;
#define GET_CTX_RET(failure_ret) \
if(!s_eglIface) return failure_ret; \
GLEScontext *ctx = s_eglIface->getGLESContext(); \
if(!ctx) return failure_ret;
#define GET_CTX_CM_RET(failure_ret) \
if(!s_eglIface) return failure_ret; \
GLEScmContext *ctx = static_cast<GLEScmContext *>(s_eglIface->getGLESContext()); \
if(!ctx) return failure_ret;
#define GET_CTX_V2_RET(failure_ret) \
if(!s_eglIface) return failure_ret; \
GLESv2Context *ctx = static_cast<GLESv2Context *>(s_eglIface->getGLESContext()); \
if(!ctx) return failure_ret;
#define SET_ERROR_IF(condition,err) if((condition)) { \
fprintf(stderr, "%s:%s:%d error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
ctx->setGLerror(err); \
return; \
}
#define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \
fprintf(stderr, "%s:%s:%d error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
ctx->setGLerror(err); \
return ret; \
}
#endif

View file

@ -0,0 +1,58 @@
/*
* 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.
*/
#ifndef GLES_POINTER_H
#define GLES_POINTER_H
#include <GLES/gl.h>
#include "GLESbuffer.h"
class GLESpointer
{
public:
GLESpointer();
GLenum getType() const;
GLint getSize() const;
GLsizei getStride() const;
const GLvoid* getArrayData() const;
GLvoid* getBufferData() const;
GLuint getBufferName() const;
GLboolean getNormalized() const { return m_normalize ? GL_TRUE : GL_FALSE; }
const GLvoid* getData() const;
unsigned int getBufferOffset() const;
void redirectPointerData();
void getBufferConversions(const RangeList& rl,RangeList& rlOut);
bool bufferNeedConversion(){ return !m_buffer->fullyConverted();}
void setArray (GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize = false);
void setBuffer(GLint size,GLenum type,GLsizei stride,GLESbuffer* buf,GLuint bufferName,int offset,bool normalize = false);
bool isEnable() const;
bool isNormalize() const;
bool isVBO() const;
void enable(bool b);
private:
GLint m_size;
GLenum m_type;
GLsizei m_stride;
bool m_enabled;
bool m_normalize;
const GLvoid* m_data;
GLESbuffer* m_buffer;
GLuint m_bufferName;
unsigned int m_buffOffset;
bool m_isVBO;
};
#endif

View file

@ -0,0 +1,44 @@
/*
* 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.
*/
#ifndef GLES_VALIDATE_H
#define GLES_VALIDATE_H
#include <GLES/gl.h>
#include "GLEScontext.h"
struct GLESvalidate
{
static bool textureEnum(GLenum e,unsigned int maxTex);
static bool pixelType(GLEScontext * ctx,GLenum type);
static bool pixelOp(GLenum format,GLenum type);
static bool pixelFrmt(GLEScontext* ctx , GLenum format);
static bool bufferTarget(GLenum target);
static bool bufferUsage(GLenum usage);
static bool bufferParam(GLenum param);
static bool drawMode(GLenum mode);
static bool drawType(GLenum mode);
static bool textureTarget(GLenum target);
static bool textureTargetLimited(GLenum target);
static bool textureTargetEx(GLenum target);
static bool texImgDim(GLsizei width,GLsizei height,int maxTexSize);
static bool blendEquationMode(GLenum mode);
static bool framebufferTarget(GLenum target);
static bool framebufferAttachment(GLenum attachment);
static bool framebufferAttachmentParams(GLenum pname);
static bool renderbufferTarget(GLenum target);
static bool renderbufferParams(GLenum pname);
};
#endif

View file

@ -0,0 +1,36 @@
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GLCOMMON_GL_LIBRARY_H
#define GLCOMMON_GL_LIBRARY_H
// An interface class used to model the desktop GL library to use at runtime.
// Use GlLibrary::getHostInstance() to retrieve the instance corresponding
// to the host's default system GL library.
class GlLibrary {
public:
// Generic pointer-to-function type.
typedef void (*GlFunctionPointer)(void);
// Empty constructor.
GlLibrary() {}
// Empty destructor.
virtual ~GlLibrary() {}
// Find the function named |name| in the library and return its address.
virtual GlFunctionPointer findSymbol(const char* name) = 0;
};
#endif // GLCOMMON_GL_LIBRARY_H

View file

@ -0,0 +1,31 @@
/*
* 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.
*/
#ifndef _GL_FIXED_OPS_H
#define _GL_FIXED_OPS_H
#define X2F(x) (((float)(x))/65536.0f)
#define X2D(x) (((double)(x))/65536.0)
#define X2I(x) ((x) /65536)
#define B2S(x) ((short)x)
#define F2X(d) ((d) > 32767.65535 ? 32767 * 65536 + 65535 : \
(d) < -32768.65535 ? -32768 * 65536 + 65535 : \
((GLfixed) ((d) * 65536)))
#define I2X(d) ((d)*65536)
#endif

View file

@ -0,0 +1,54 @@
/*
* 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.
*/
#ifndef GL_UTILS_H
#define GL_UTILS_H
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
typedef enum {
GLES_1_1 = 1,
GLES_2_0 = 2,
MAX_GLES_VERSION //Must be last
} GLESVersion;
bool isPowerOf2(int num);
// <EGL/egl.h> defines many types as 'void*' while they're really
// implemented as unsigned integers. These convenience template functions
// help casting between them safely without generating compiler warnings.
inline void* SafePointerFromUInt(unsigned int handle) {
return (void*)(uintptr_t)(handle);
}
inline unsigned int SafeUIntFromPointer(const void* ptr) {
#if 1
// Ignore the assert below to avoid crashing when running older
// system images, which might have buggy encoder libraries. Print
// an error message though.
if ((uintptr_t)(ptr) != (unsigned int)(uintptr_t)(ptr)) {
fprintf(stderr, "EmuGL:WARNING: bad generic pointer %p\n", ptr);
}
#else
// Assertion error if the pointer contains a value that does not fit
// in an unsigned integer!
assert((uintptr_t)(ptr) == (unsigned int)(uintptr_t)(ptr));
#endif
return (unsigned int)(uintptr_t)(ptr);
}
#endif

View file

@ -0,0 +1,25 @@
/*
* 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.
*/
#ifndef __PALETTE_TEXTURE_H__
#define __PALETTE_TEXTURE_H__
#include <GLES/gl.h>
#define MAX_SUPPORTED_PALETTE 10
unsigned char* uncompressTexture(GLenum internalformat,GLenum& formatOut,GLsizei width,GLsizei height,GLsizei imageSize, const GLvoid* data,GLint level);
#endif

View file

@ -0,0 +1,69 @@
/*
* 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.
*/
#ifndef RANGE_H
#define RANGE_H
#include <vector>
class Range {
public:
Range():m_start(0),m_end(0),m_size(0){};
Range(int start,int size):m_start(start),m_end(start+size),m_size(size){};
Range(const Range& r):m_start(r.m_start),m_end(r.m_end),m_size(r.m_size){};
void setRange(int start,int size){m_start = start; m_end = start+size; m_size = size;};
inline int getStart() const{return m_start;};
inline int getEnd() const{return m_end;};
inline int getSize() const{return m_size;};
Range& operator=(const Range& r) {
m_start = r.m_start;
m_end = r.m_end;
m_size = r.m_size;
return *this;
}
bool operator ==(const Range& r) const {
return m_start == r.m_start && m_size == r.m_size && m_end == r.m_end;
}
bool operator !=(const Range& r) const {return !((*this) == r);};
bool rangeIntersection(const Range& r,Range& rOut) const ;
bool rangeUnion(const Range& r,Range& rOut) const ;
private:
int m_start;
int m_end;
int m_size;
};
class RangeList {
public:
void addRange(const Range& r);
void addRanges(const RangeList& rl);
void delRange(const Range& r,RangeList& deleted);
void delRanges(const RangeList& rl,RangeList& deleted);
bool empty() const;
void merge();
int size() const;
void clear();
Range& operator[](unsigned int i){return list[i];};
private:
void erase(unsigned int i);
std::vector<Range> list;
};
#endif

View file

@ -0,0 +1,31 @@
/*
* 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.
*/
#ifndef _TEXTURE_UTILS_H
#define _TEXTURE_UTILS_H
#include <GLES/gl.h>
#include <GLES/glext.h>
#include "GLEScontext.h"
#include "PaletteTexture.h"
#include "etc1.h"
int getCompressedFormats(int* formats);
void doCompressedTexImage2D(GLEScontext * ctx, GLenum target, GLint level,
GLenum internalformat, GLsizei width,
GLsizei height, GLint border,
GLsizei imageSize, const GLvoid* data, void * funcPtr);
#endif

View file

@ -0,0 +1,120 @@
/*
* 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.
*/
#ifndef TRANSLATOR_IFACES_H
#define TRANSLATOR_IFACES_H
#include "GLcommon/objectNameManager.h"
#include <GLES/gl.h>
#include <string.h>
extern "C" {
/* This is a generic function pointer type, whose name indicates it must
* be cast to the proper type *and calling convention* before use.
*/
typedef void (*__translatorMustCastToProperFunctionPointerType)(void);
typedef struct {
const char* name;
__translatorMustCastToProperFunctionPointerType address;
}ExtentionDescriptor;
class TextureData : public ObjectData
{
public:
~TextureData() {
if (sourceEGLImage && eglImageDetach) (*eglImageDetach)(sourceEGLImage);
}
TextureData(): ObjectData(TEXTURE_DATA),
width(0),
height(0),
border(0),
internalFormat(GL_RGBA),
sourceEGLImage(0),
wasBound(false),
requiresAutoMipmap(false),
target(0),
oldGlobal(0) {
memset(crop_rect,0,4*sizeof(int));
};
unsigned int width;
unsigned int height;
unsigned int border;
unsigned int internalFormat;
unsigned int sourceEGLImage;
bool wasBound;
bool requiresAutoMipmap;
int crop_rect[4];
void (*eglImageDetach)(unsigned int imageId);
GLenum target;
GLuint oldGlobal;
};
struct EglImage
{
~EglImage(){};
unsigned int imageId;
unsigned int globalTexName;
unsigned int width;
unsigned int height;
unsigned int internalFormat;
unsigned int border;
};
typedef emugl::SmartPtr<EglImage> ImagePtr;
typedef std::map< unsigned int, ImagePtr> ImagesHndlMap;
class GLEScontext;
typedef struct {
void (*initGLESx)();
GLEScontext* (*createGLESContext)();
void (*initContext)(GLEScontext*,ShareGroupPtr);
void (*deleteGLESContext)(GLEScontext*);
void (*flush)();
void (*finish)();
void (*setShareGroup)(GLEScontext*,ShareGroupPtr);
__translatorMustCastToProperFunctionPointerType (*getProcAddress)(const char*);
}GLESiface;
class GlLibrary;
// A structure containing function pointers implemented by the EGL
// translator library, and called from the GLES 1.x and 2.0 translator
// libraries.
struct EGLiface {
// Get the current GLESContext instance for the current thread.
GLEScontext* (*getGLESContext)();
// Create a new global EglImage object named |imageId| and return a
// pointer to its new instance.
EglImage* (*eglAttachEGLImage)(unsigned int imageId);
// Release a global EglImage instance named |imageId|.
void (*eglDetachEGLImage)(unsigned int imageId);
// Return instance of GlLibrary class to use for dispatch.
// at runtime. This is implemented in the EGL library because on Windows
// all functions returned by wglGetProcAddress() are context-dependent!
GlLibrary* (*eglGetGlLibrary)();
};
typedef GLESiface* (*__translator_getGLESIfaceFunc)(const EGLiface*);
}
#endif

View file

@ -0,0 +1,108 @@
// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __etc1_h__
#define __etc1_h__
#define MAX_ETC_SUPPORTED 1
#define ETC1_ENCODED_BLOCK_SIZE 8
#define ETC1_DECODED_BLOCK_SIZE 48
#ifndef ETC1_RGB8_OES
#define ETC1_RGB8_OES 0x8D64
#endif
typedef unsigned char etc1_byte;
typedef int etc1_bool;
typedef unsigned int etc1_uint32;
#ifdef __cplusplus
extern "C" {
#endif
// Encode a block of pixels.
//
// pIn is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
// value of pixel (x, y).
//
// validPixelMask is a 16-bit mask where bit (1 << (x + y * 4)) indicates whether
// the corresponding (x,y) pixel is valid. Invalid pixel color values are ignored when compressing.
//
// pOut is an ETC1 compressed version of the data.
void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 validPixelMask, etc1_byte* pOut);
// Decode a block of pixels.
//
// pIn is an ETC1 compressed version of the data.
//
// pOut is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
// value of pixel (x, y).
void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut);
// Return the size of the encoded image data (does not include size of PKM header).
etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height);
// Encode an entire image.
// pIn - pointer to the image data. Formatted such that
// pixel (x,y) is at pIn + pixelSize * x + stride * y;
// pOut - pointer to encoded data. Must be large enough to store entire encoded image.
// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image.
// returns non-zero if there is an error.
int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height,
etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut);
// Decode an entire image.
// pIn - pointer to encoded data.
// pOut - pointer to the image data. Will be written such that
// pixel (x,y) is at pIn + pixelSize * x + stride * y. Must be
// large enough to store entire image.
// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image.
// returns non-zero if there is an error.
int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut,
etc1_uint32 width, etc1_uint32 height,
etc1_uint32 pixelSize, etc1_uint32 stride);
// Size of a PKM header, in bytes.
#define ETC_PKM_HEADER_SIZE 16
// Format a PKM header
void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height);
// Check if a PKM header is correctly formatted.
etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader);
// Read the image width from a PKM header
etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader);
// Read the image height from a PKM header
etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,269 @@
/*
* 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.
*/
#ifndef _OBJECT_NAME_MANAGER_H
#define _OBJECT_NAME_MANAGER_H
#include <map>
#include "emugl/common/mutex.h"
#include "emugl/common/smart_ptr.h"
enum NamedObjectType {
VERTEXBUFFER = 0,
TEXTURE = 1,
RENDERBUFFER = 2,
FRAMEBUFFER = 3,
SHADER = 4,
NUM_OBJECT_TYPES = 5 // Must be last
};
enum ObjectDataType {
SHADER_DATA,
PROGRAM_DATA,
TEXTURE_DATA,
BUFFER_DATA,
UNDEFINED_DATA
};
class ObjectData
{
public:
ObjectData() : m_dataType(UNDEFINED_DATA) {};
ObjectData(ObjectDataType type): m_dataType(type) {};
ObjectDataType getDataType() { return m_dataType; };
virtual ~ObjectData() {};
private:
ObjectDataType m_dataType;
};
typedef emugl::SmartPtr<ObjectData> ObjectDataPtr;
typedef unsigned long long ObjectLocalName;
typedef std::map<ObjectLocalName, unsigned int> NamesMap;
//
// Class NameSpace - this class manages allocations and deletions of objects
// from a single "local" namespace (private to context group).
// For each allocated object name, a "global" name is
// generated as well to be used in the space where all
// contexts are shared.
//
// NOTE: this class does not used by the EGL/GLES layer directly,
// the EGL/GLES layer creates objects using the ShareGroup class
// interface (see below).
class GlobalNameSpace;
class NameSpace
{
friend class ShareGroup;
friend class GlobalNameSpace;
private:
NameSpace(NamedObjectType p_type, GlobalNameSpace *globalNameSpace);
~NameSpace();
//
// genName - creates new object in the namespace and returns its name.
// if genLocal is false then the specified p_localName will be used.
// This function also generate a global name for the object,
// the value of the global name can be retrieved using the
// getGlobalName function.
//
ObjectLocalName genName(ObjectLocalName p_localName, bool genGlobal, bool genLocal);
// genGlobalName() - This function creates a global name
// with no associated local name, for the
// translator internal use.
unsigned int genGlobalName(void);
//
// getGlobalName - returns the global name of an object or 0 if the object
// does not exist.
//
unsigned int getGlobalName(ObjectLocalName p_localName);
//
// getLocaalName - returns the local name of an object or 0 if the object
// does not exist.
//
ObjectLocalName getLocalName(unsigned int p_globalName);
//
// deleteName - deletes and object from the namespace as well as its
// global name from the global name space.
//
void deleteName(ObjectLocalName p_localName);
//
// isObject - returns true if the named object exist.
//
bool isObject(ObjectLocalName p_localName);
//
// replaces an object to map to an existing global object
//
void replaceGlobalName(ObjectLocalName p_localName, unsigned int p_globalName);
private:
ObjectLocalName m_nextName;
NamesMap m_localToGlobalMap;
const NamedObjectType m_type;
GlobalNameSpace *m_globalNameSpace;
};
class GlobalNameSpace
{
public:
GlobalNameSpace();
~GlobalNameSpace();
unsigned int genName(NamedObjectType p_type);
void deleteName(NamedObjectType p_type, unsigned int p_name);
private:
emugl::Mutex m_lock;
};
//
// class ShareGroup -
// That class manages objects of one "local" context share group, typically
// there will be one inctance of ShareGroup for each user OpenGL context
// unless the user context share with another user context. In that case they
// both will share the same ShareGroup instance.
// calls into that class gets serialized through a lock so it is thread safe.
//
class ShareGroup
{
friend class ObjectNameManager;
friend class emugl::SmartPtr<ShareGroup>; // to allow destructing when ShareGroupPtr refcount reaches zero
public:
//
// genName - generates new object name and returns its name value.
// if genLocal is false, p_localName will be used as the name.
// This function also generates a "global" name for the object
// which can be queried using the getGlobalName function.
//
ObjectLocalName genName(NamedObjectType p_type, ObjectLocalName p_localName = 0, bool genLocal= false);
// genGlobalName() - This function creates a global name
// with no associated local name, for the
// translator internal use.
unsigned int genGlobalName(NamedObjectType p_type);
//
// getGlobalName - retrieves the "global" name of an object or 0 if the
// object does not exist.
//
unsigned int getGlobalName(NamedObjectType p_type, ObjectLocalName p_localName);
//
// getLocalName - retrieves the "local" name of an object or 0 if the
// object does not exist.
//
ObjectLocalName getLocalName(NamedObjectType p_type, unsigned int p_globalName);
//
// deleteName - deletes and object from the namespace as well as its
// global name from the global name space.
//
void deleteName(NamedObjectType p_type, ObjectLocalName p_localName);
//
// replaceGlobalName - replaces an object to map to an existing global
// named object. (used when creating EGLImage siblings)
//
void replaceGlobalName(NamedObjectType p_type, ObjectLocalName p_localName, unsigned int p_globalName);
//
// isObject - returns true if the named object exist.
//
bool isObject(NamedObjectType p_type, ObjectLocalName p_localName);
//
// Assign object global data to a names object
//
void setObjectData(NamedObjectType p_type, ObjectLocalName p_localName, ObjectDataPtr data);
//
// Retrieve object global data
//
ObjectDataPtr getObjectData(NamedObjectType p_type, ObjectLocalName p_localName);
private:
explicit ShareGroup(GlobalNameSpace *globalNameSpace);
~ShareGroup();
private:
emugl::Mutex m_lock;
NameSpace *m_nameSpace[NUM_OBJECT_TYPES];
void *m_objectsData;
};
typedef emugl::SmartPtr<ShareGroup> ShareGroupPtr;
typedef std::multimap<void *, ShareGroupPtr> ShareGroupsMap;
//
// ObjectNameManager -
// This class manages the set of all ShareGroups instances,
// each ShareGroup instance can be accessed through one or more 'groupName'
// values. the type of 'groupName' is void *, the intent is that the EGL
// layer will use the user context handle as the name for its ShareGroup
// object. Multiple names can be attached to a ShareGroup object to support
// user context sharing.
//
class ObjectNameManager
{
public:
explicit ObjectNameManager(GlobalNameSpace *globalNameSpace);
~ObjectNameManager();
//
// createShareGroup - create a new ShareGroup object and attach it with
// the "name" specified by p_groupName.
//
ShareGroupPtr createShareGroup(void *p_groupName);
//
// attachShareGroup - find the ShareGroup object attached to the name
// specified in p_existingGroupName and attach p_groupName to the same
// ShareGroup instance.
//
ShareGroupPtr attachShareGroup(void *p_groupName, void *p_existingGroupName);
//
// getShareGroup - retreive a ShareGroup object based on its "name"
//
ShareGroupPtr getShareGroup(void *p_groupName);
//
// deleteShareGroup - deletes the attachment of the p_groupName to its
// attached ShareGroup. When the last name of ShareGroup is
// deleted the ShareGroup object is destroyed.
//
void deleteShareGroup(void *p_groupName);
//
// getGlobalContext() - this function returns a name of an existing
// ShareGroup. The intent is that the EGL layer will
// use that function to get the GL context which each
// new context needs to share with.
//
void *getGlobalContext();
private:
ShareGroupsMap m_groups;
emugl::Mutex m_lock;
GlobalNameSpace *m_globalNameSpace;
};
#endif

View file

@ -92,14 +92,8 @@ private:
// eg.
// on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo"
#if defined(__x86_64__)
# define EMUGL_LIBNAME(name) "lib64" name
#elif defined(__i386__)
# define EMUGL_LIBNAME(name) "lib" name
#else
/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */
# define EMUGL_LIBNAME(name) "lib" name
#endif
} // namespace emugl