blob: f116f25956e3e6d4eb92396292d2fd6b95231b65 [file] [log] [blame]
/* Copyright (C) 2011 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
#include "config-host.h"
#include "android/opengles.h"
#include "android/globals.h"
#include <android/utils/debug.h>
#include <android/utils/path.h>
#include <android/utils/bufprint.h>
#include <android/utils/dll.h>
#include <stdio.h>
#include <stdlib.h>
#define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
#define DD(...) VERBOSE_PRINT(gles,__VA_ARGS__)
/* Declared in "android/globals.h" */
int android_gles_fast_pipes = 1;
/* Name of the GLES rendering library we're going to use */
#if HOST_LONG_BITS == 32
#define RENDERER_LIB_NAME "libOpenglRender"
#elif HOST_LONG_BITS == 64
#define RENDERER_LIB_NAME "lib64OpenglRender"
#else
#error Unknown HOST_LONG_BITS
#endif
/* These definitions *must* match those under:
* development/tools/emulator/opengl/host/include/libOpenglRender/render_api.h
*/
#define DYNLINK_FUNCTIONS \
DYNLINK_FUNC(int,initLibrary,(void),(),return) \
DYNLINK_FUNC(int,setStreamMode,(int a),(a),return) \
DYNLINK_FUNC(int,initOpenGLRenderer,(int width, int height, int port, OnPostFn onPost, void* onPostContext),(width,height,port,onPost,onPostContext),return) \
DYNLINK_FUNC(int,createOpenGLSubwindow,(void* window, int x, int y, int width, int height, float zRot),(window,x,y,width,height,zRot),return)\
DYNLINK_FUNC(int,destroyOpenGLSubwindow,(void),(),return)\
DYNLINK_FUNC(void,repaintOpenGLDisplay,(void),(),)\
DYNLINK_FUNC(void,stopOpenGLRenderer,(void),(),)
#define STREAM_MODE_DEFAULT 0
#define STREAM_MODE_TCP 1
#define STREAM_MODE_UNIX 2
#define STREAM_MODE_PIPE 3
#ifndef CONFIG_STANDALONE_UI
/* Defined in android/hw-pipe-net.c */
extern int android_init_opengles_pipes(void);
#endif
static ADynamicLibrary* rendererLib;
/* Define the pointers and the wrapper functions to call them */
#define DYNLINK_FUNC(result,name,sig,params,ret) \
static result (*_ptr_##name) sig; \
static result name sig { \
ret (*_ptr_##name) params ; \
}
DYNLINK_FUNCTIONS
#undef DYNLINK_FUNC
static int
initOpenglesEmulationFuncs(ADynamicLibrary* rendererLib)
{
void* symbol;
char* error;
#define DYNLINK_FUNC(result,name,sig,params,ret) \
symbol = adynamicLibrary_findSymbol( rendererLib, #name, &error ); \
if (symbol != NULL) { \
_ptr_##name = symbol; \
} else { \
derror("GLES emulation: Could not find required symbol (%s): %s", #name, error); \
free(error); \
return -1; \
}
DYNLINK_FUNCTIONS
#undef DYNLINK_FUNC
return 0;
}
int
android_initOpenglesEmulation(void)
{
char* error = NULL;
if (rendererLib != NULL)
return 0;
D("Initializing hardware OpenGLES emulation support");
rendererLib = adynamicLibrary_open(RENDERER_LIB_NAME, &error);
if (rendererLib == NULL) {
derror("Could not load OpenGLES emulation library: %s", error);
return -1;
}
#ifndef CONFIG_STANDALONE_UI
android_init_opengles_pipes();
#endif
/* Resolve the functions */
if (initOpenglesEmulationFuncs(rendererLib) < 0) {
derror("OpenGLES emulation library mismatch. Be sure to use the correct version!");
goto BAD_EXIT;
}
if (!initLibrary()) {
derror("OpenGLES initialization failed!");
goto BAD_EXIT;
}
if (android_gles_fast_pipes) {
#ifdef _WIN32
/* XXX: NEED Win32 pipe implementation */
setStreamMode(STREAM_MODE_TCP);
#else
setStreamMode(STREAM_MODE_UNIX);
#endif
} else {
setStreamMode(STREAM_MODE_TCP);
}
return 0;
BAD_EXIT:
derror("OpenGLES emulation library could not be initialized!");
adynamicLibrary_close(rendererLib);
rendererLib = NULL;
return -1;
}
int
android_startOpenglesRenderer(int width, int height, OnPostFn onPost, void* onPostContext)
{
if (!rendererLib) {
D("Can't start OpenGLES renderer without support libraries");
return -1;
}
if (initOpenGLRenderer(width, height, ANDROID_OPENGLES_BASE_PORT, onPost, onPostContext) != 0) {
D("Can't start OpenGLES renderer?");
return -1;
}
return 0;
}
void
android_stopOpenglesRenderer(void)
{
if (rendererLib) {
stopOpenGLRenderer();
}
}
int
android_showOpenglesWindow(void* window, int x, int y, int width, int height, float rotation)
{
if (rendererLib) {
return createOpenGLSubwindow(window, x, y, width, height, rotation);
} else {
return -1;
}
}
int
android_hideOpenglesWindow(void)
{
if (rendererLib) {
return destroyOpenGLSubwindow();
} else {
return -1;
}
}
void
android_redrawOpenglesWindow(void)
{
if (rendererLib) {
repaintOpenGLDisplay();
}
}
void
android_gles_unix_path(char* buff, size_t buffsize, int port)
{
const char* user = getenv("USER");
char *p = buff, *end = buff + buffsize;
/* The logic here must correspond to the one inside
* development/tools/emulator/opengl/shared/libOpenglCodecCommon/UnixStream.cpp */
p = bufprint(p, end, "/tmp/");
if (user && user[0]) {
p = bufprint(p, end, "android-%s/", user);
}
p = bufprint(p, end, "qemu-gles-%d", port);
}