mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
Android support, part 2 (display module)
This commit is contained in:
parent
c26c0e6a97
commit
0631441b20
@ -9,7 +9,7 @@
|
||||
#define BUILD_DIRECTORY $[HAVE_GLES]
|
||||
|
||||
#define COMPONENT_LIBS \
|
||||
p3glesgsg p3egldisplay
|
||||
p3glesgsg p3egldisplay p3androiddisplay
|
||||
|
||||
#define LOCAL_LIBS p3gsgbase p3display p3express
|
||||
#define OTHER_LIBS p3interrogatedb:c p3dconfig:c p3dtoolconfig:m \
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Filename: pandagles.cxx
|
||||
// Created by: pro-rsoft (8Jun09)
|
||||
// Created by: rdb (8Jun09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -8,7 +8,10 @@
|
||||
#define OPENGLES_1
|
||||
#include "config_glesgsg.h"
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#if defined(ANDROID)
|
||||
#include "config_androiddisplay.h"
|
||||
#include "androidGraphicsPipe.h"
|
||||
#elif defined(HAVE_EGL)
|
||||
#include "config_egldisplay.h"
|
||||
#include "eglGraphicsPipe.h"
|
||||
#endif
|
||||
@ -31,7 +34,9 @@ void
|
||||
init_libpandagles() {
|
||||
init_libglesgsg();
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#if defined(ANDROID)
|
||||
init_libandroiddisplay();
|
||||
#elif defined(HAVE_EGL)
|
||||
init_libegldisplay();
|
||||
#endif
|
||||
}
|
||||
@ -43,7 +48,9 @@ init_libpandagles() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
get_pipe_type_pandagles() {
|
||||
#ifdef HAVE_EGL
|
||||
#if defined(ANDROID)
|
||||
return AndroidGraphicsPipe::get_class_type().get_index();
|
||||
#elif defined(HAVE_EGL)
|
||||
return eglGraphicsPipe::get_class_type().get_index();
|
||||
#endif
|
||||
|
||||
|
14
panda/src/androiddisplay/androidGraphicsPipe.I
Normal file
14
panda/src/androiddisplay/androidGraphicsPipe.I
Normal file
@ -0,0 +1,14 @@
|
||||
// Filename: androidGraphicsPipe.I
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
233
panda/src/androiddisplay/androidGraphicsPipe.cxx
Normal file
233
panda/src/androiddisplay/androidGraphicsPipe.cxx
Normal file
@ -0,0 +1,233 @@
|
||||
// Filename: androidGraphicsPipe.cxx
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#include "androidGraphicsBuffer.h"
|
||||
#include "androidGraphicsPipe.h"
|
||||
//#include "androidGraphicsPixmap.h"
|
||||
#include "androidGraphicsWindow.h"
|
||||
#include "androidGraphicsStateGuardian.h"
|
||||
#include "config_androiddisplay.h"
|
||||
#include "frameBufferProperties.h"
|
||||
|
||||
TypeHandle AndroidGraphicsPipe::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsPipe::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AndroidGraphicsPipe::
|
||||
AndroidGraphicsPipe() {
|
||||
_is_valid = false;
|
||||
_supported_types = OT_window | OT_buffer | OT_texture_buffer;
|
||||
_egl_display = NULL;
|
||||
|
||||
_display_width = 0;
|
||||
_display_height = 0;
|
||||
|
||||
_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (!eglInitialize(_egl_display, NULL, NULL)) {
|
||||
androiddisplay_cat.error()
|
||||
<< "Couldn't initialize the EGL display: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
|
||||
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
|
||||
androiddisplay_cat.error()
|
||||
<< "Couldn't bind EGL to the OpenGL ES API: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsPipe::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AndroidGraphicsPipe::
|
||||
~AndroidGraphicsPipe() {
|
||||
if (_egl_display) {
|
||||
if (!eglTerminate(_egl_display)) {
|
||||
androiddisplay_cat.error() << "Failed to terminate EGL display: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsPipe::get_interface_name
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns the name of the rendering interface
|
||||
// associated with this GraphicsPipe. This is used to
|
||||
// present to the user to allow him/her to choose
|
||||
// between several possible GraphicsPipes available on a
|
||||
// particular platform, so the name should be meaningful
|
||||
// and unique for a given platform.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string AndroidGraphicsPipe::
|
||||
get_interface_name() const {
|
||||
return "OpenGL ES";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsPipe::pipe_constructor
|
||||
// Access: Public, Static
|
||||
// Description: This function is passed to the GraphicsPipeSelection
|
||||
// object to allow the user to make a default
|
||||
// AndroidGraphicsPipe.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(GraphicsPipe) AndroidGraphicsPipe::
|
||||
pipe_constructor() {
|
||||
return new AndroidGraphicsPipe;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsPipe::get_preferred_window_thread
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns an indication of the thread in which this
|
||||
// GraphicsPipe requires its window processing to be
|
||||
// performed: typically either the app thread (e.g. X)
|
||||
// or the draw thread (Windows).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsPipe::PreferredWindowThread
|
||||
AndroidGraphicsPipe::get_preferred_window_thread() const {
|
||||
// Most of the Android NDK window functions can be
|
||||
// called from any thread. Since we're creating the
|
||||
// context at open_window time, let's choose "draw".
|
||||
return PWT_app;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsPipe::make_output
|
||||
// Access: Protected, Virtual
|
||||
// Description: Creates a new window on the pipe, if possible.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(GraphicsOutput) AndroidGraphicsPipe::
|
||||
make_output(const string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsEngine *engine,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host,
|
||||
int retry,
|
||||
bool &precertify) {
|
||||
|
||||
if (!_is_valid) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AndroidGraphicsStateGuardian *androidgsg = 0;
|
||||
if (gsg != 0) {
|
||||
DCAST_INTO_R(androidgsg, gsg, NULL);
|
||||
}
|
||||
|
||||
// First thing to try: an eglGraphicsWindow
|
||||
|
||||
if (retry == 0) {
|
||||
if (((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_refuse_window)!=0)||
|
||||
((flags&BF_resizeable)!=0)||
|
||||
((flags&BF_size_track_host)!=0)||
|
||||
((flags&BF_rtt_cumulative)!=0)||
|
||||
((flags&BF_can_bind_color)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
return new AndroidGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
||||
// Second thing to try: a GLES(2)GraphicsBuffer
|
||||
/*if (retry == 1) {
|
||||
if ((host==0)||
|
||||
// (!gl_support_fbo)||
|
||||
((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
// Early failure - if we are sure that this buffer WONT
|
||||
// meet specs, we can bail out early.
|
||||
if ((flags & BF_fb_props_optional)==0) {
|
||||
if ((fb_prop.get_indexed_color() > 0)||
|
||||
(fb_prop.get_back_buffers() > 0)||
|
||||
(fb_prop.get_accum_bits() > 0)||
|
||||
(fb_prop.get_multisamples() > 0)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// Early success - if we are sure that this buffer WILL
|
||||
// meet specs, we can precertify it.
|
||||
if ((eglgsg != 0) &&
|
||||
(eglgsg->is_valid()) &&
|
||||
(!eglgsg->needs_reset()) &&
|
||||
(eglgsg->_supports_framebuffer_object) &&
|
||||
(eglgsg->_glDrawBuffers != 0)&&
|
||||
(fb_prop.is_basic())) {
|
||||
precertify = true;
|
||||
}
|
||||
#ifdef OPENGLES_2
|
||||
return new GLES2GraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
#else
|
||||
return new GLESGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Third thing to try: a eglGraphicsBuffer
|
||||
if (retry == 2) {
|
||||
if (((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)||
|
||||
((flags&BF_resizeable)!=0)||
|
||||
((flags&BF_size_track_host)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!support_rtt) {
|
||||
if (((flags&BF_rtt_cumulative)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
// If we require Render-to-Texture, but can't be sure we
|
||||
// support it, bail.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return new eglGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
||||
// Fourth thing to try: an eglGraphicsPixmap.
|
||||
if (retry == 3) {
|
||||
if (((flags&BF_require_parasite)!=0)||
|
||||
((flags&BF_require_window)!=0)||
|
||||
((flags&BF_resizeable)!=0)||
|
||||
((flags&BF_size_track_host)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (((flags&BF_rtt_cumulative)!=0)||
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new eglGraphicsPixmap(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}*/
|
||||
|
||||
// Nothing else left to try.
|
||||
return NULL;
|
||||
}
|
94
panda/src/androiddisplay/androidGraphicsPipe.h
Normal file
94
panda/src/androiddisplay/androidGraphicsPipe.h
Normal file
@ -0,0 +1,94 @@
|
||||
// Filename: androidGraphicsPipe.h
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ANDROIDGRAPHICSPIPE_H
|
||||
#define ANDROIDGRAPHICSPIPE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsPipe.h"
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
#include "gles2gsg.h"
|
||||
// #define NativeDisplayType EGLNativeDisplayType
|
||||
// #define NativePixmapType EGLNativePixmapType
|
||||
// #define NativeWindowType EGLNativeWindowType
|
||||
#else
|
||||
#include "glesgsg.h"
|
||||
#endif
|
||||
#include <EGL/egl.h>
|
||||
|
||||
class FrameBufferProperties;
|
||||
|
||||
class AndroidGraphicsBuffer;
|
||||
class AndroidGraphicsPixmap;
|
||||
class AndroidGraphicsWindow;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AndroidGraphicsPipe
|
||||
// Description : This graphics pipe represents the interface for
|
||||
// creating OpenGL ES graphics windows on an X-based
|
||||
// (e.g. Unix) client.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class AndroidGraphicsPipe : public GraphicsPipe {
|
||||
public:
|
||||
AndroidGraphicsPipe();
|
||||
virtual ~AndroidGraphicsPipe();
|
||||
|
||||
virtual string get_interface_name() const;
|
||||
static PT(GraphicsPipe) pipe_constructor();
|
||||
|
||||
public:
|
||||
virtual PreferredWindowThread get_preferred_window_thread() const;
|
||||
|
||||
protected:
|
||||
virtual PT(GraphicsOutput) make_output(const string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsEngine *engine,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host,
|
||||
int retry,
|
||||
bool &precertify);
|
||||
|
||||
private:
|
||||
EGLDisplay _egl_display;
|
||||
GraphicsWindow *_window;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
GraphicsPipe::init_type();
|
||||
register_type(_type_handle, "AndroidGraphicsPipe",
|
||||
GraphicsPipe::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class AndroidGraphicsBuffer;
|
||||
friend class AndroidGraphicsPixmap;
|
||||
friend class AndroidGraphicsWindow;
|
||||
};
|
||||
|
||||
#include "androidGraphicsPipe.I"
|
||||
|
||||
#endif
|
25
panda/src/androiddisplay/androidGraphicsStateGuardian.I
Normal file
25
panda/src/androiddisplay/androidGraphicsStateGuardian.I
Normal file
@ -0,0 +1,25 @@
|
||||
// Filename: androidGraphicsStateGuardian.I
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::get_fb_properties
|
||||
// Access: Private
|
||||
// Description: Gets the FrameBufferProperties for all windows and
|
||||
// buffers that use this GSG.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const FrameBufferProperties &AndroidGraphicsStateGuardian::
|
||||
get_fb_properties() const {
|
||||
return _fbprops;
|
||||
}
|
403
panda/src/androiddisplay/androidGraphicsStateGuardian.cxx
Normal file
403
panda/src/androiddisplay/androidGraphicsStateGuardian.cxx
Normal file
@ -0,0 +1,403 @@
|
||||
// Filename: androidGraphicsStateGuardian.cxx
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "androidGraphicsStateGuardian.h"
|
||||
#include "config_androiddisplay.h"
|
||||
#include "lightReMutexHolder.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
TypeHandle AndroidGraphicsStateGuardian::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AndroidGraphicsStateGuardian::
|
||||
AndroidGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
AndroidGraphicsStateGuardian *share_with) :
|
||||
#ifdef OPENGLES_2
|
||||
GLES2GraphicsStateGuardian(engine, pipe)
|
||||
#else
|
||||
GLESGraphicsStateGuardian(engine, pipe)
|
||||
#endif
|
||||
{
|
||||
_share_context = 0;
|
||||
_context = 0;
|
||||
_egl_display = 0;
|
||||
_fbconfig = 0;
|
||||
_format = 0;
|
||||
|
||||
if (share_with != (AndroidGraphicsStateGuardian *)NULL) {
|
||||
_prepared_objects = share_with->get_prepared_objects();
|
||||
_share_context = share_with->_context;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AndroidGraphicsStateGuardian::
|
||||
~AndroidGraphicsStateGuardian() {
|
||||
if (_context != (EGLContext)NULL) {
|
||||
if (!eglDestroyContext(_egl_display, _context)) {
|
||||
androiddisplay_cat.error() << "Failed to destroy EGL context: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
_context = (EGLContext)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::get_properties
|
||||
// Access: Private
|
||||
// Description: Gets the FrameBufferProperties to match the
|
||||
// indicated config.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsStateGuardian::
|
||||
get_properties(FrameBufferProperties &properties,
|
||||
bool &pbuffer_supported, bool &pixmap_supported,
|
||||
bool &slow, EGLConfig config) {
|
||||
|
||||
properties.clear();
|
||||
|
||||
// Now update our framebuffer_mode and bit depth appropriately.
|
||||
EGLint red_size, green_size, blue_size,
|
||||
alpha_size,
|
||||
depth_size, stencil_size, samples, surface_type, caveat;
|
||||
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_RED_SIZE, &red_size);
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_GREEN_SIZE, &green_size);
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_BLUE_SIZE, &blue_size);
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_ALPHA_SIZE, &alpha_size);
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_DEPTH_SIZE, &depth_size);
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_STENCIL_SIZE, &stencil_size);
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_SAMPLES, &samples);
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_SURFACE_TYPE, &surface_type);
|
||||
eglGetConfigAttrib(_egl_display, config, EGL_CONFIG_CAVEAT, &caveat);
|
||||
int err = eglGetError();
|
||||
if (err != EGL_SUCCESS) {
|
||||
androiddisplay_cat.error() << "Failed to get EGL config attrib: "
|
||||
<< get_egl_error_string(err) << "\n";
|
||||
}
|
||||
|
||||
pbuffer_supported = false;
|
||||
if ((surface_type & EGL_PBUFFER_BIT)!=0) {
|
||||
pbuffer_supported = true;
|
||||
}
|
||||
|
||||
pixmap_supported = false;
|
||||
if ((surface_type & EGL_PIXMAP_BIT)!=0) {
|
||||
pixmap_supported = true;
|
||||
}
|
||||
|
||||
slow = false;
|
||||
if (caveat == EGL_SLOW_CONFIG) {
|
||||
slow = true;
|
||||
}
|
||||
|
||||
if ((surface_type & EGL_WINDOW_BIT)==0) {
|
||||
// We insist on having a context that will support an onscreen window.
|
||||
return;
|
||||
}
|
||||
|
||||
properties.set_back_buffers(1);
|
||||
properties.set_rgb_color(1);
|
||||
properties.set_color_bits(red_size+green_size+blue_size);
|
||||
properties.set_stencil_bits(stencil_size);
|
||||
properties.set_depth_bits(depth_size);
|
||||
properties.set_alpha_bits(alpha_size);
|
||||
properties.set_multisamples(samples);
|
||||
|
||||
// Set both hardware and software bits, indicating not-yet-known.
|
||||
properties.set_force_software(1);
|
||||
properties.set_force_hardware(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::choose_pixel_format
|
||||
// Access: Private
|
||||
// Description: Selects a visual or fbconfig for all the windows
|
||||
// and buffers that use this gsg.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsStateGuardian::
|
||||
choose_pixel_format(const FrameBufferProperties &properties,
|
||||
bool need_pbuffer, bool need_pixmap) {
|
||||
|
||||
_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
_fbconfig = 0;
|
||||
_format = 0;
|
||||
|
||||
int attrib_list[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
#ifdef OPENGLES_1
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
||||
#endif
|
||||
#ifdef OPENGLES_2
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
#endif
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
// First get the number of matching configurations, so we know how much memory to allocate.
|
||||
int num_configs = 0, returned_configs;
|
||||
if (!eglChooseConfig(_egl_display, attrib_list, NULL, num_configs, &returned_configs) || returned_configs <= 0) {
|
||||
androiddisplay_cat.error() << "eglChooseConfig failed: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
num_configs = returned_configs;
|
||||
EGLConfig *configs = new EGLConfig[num_configs];
|
||||
|
||||
if (!eglChooseConfig(_egl_display, attrib_list, configs, num_configs, &returned_configs) || returned_configs <= 0) {
|
||||
androiddisplay_cat.error() << "eglChooseConfig failed: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
delete[] configs;
|
||||
return;
|
||||
}
|
||||
|
||||
int best_quality = 0;
|
||||
int best_result = 0;
|
||||
FrameBufferProperties best_props;
|
||||
|
||||
for (int i = 0; i < num_configs; ++i) {
|
||||
FrameBufferProperties fbprops;
|
||||
bool pbuffer_supported, pixmap_supported, slow;
|
||||
get_properties(fbprops, pbuffer_supported, pixmap_supported,
|
||||
slow, configs[i]);
|
||||
// We're not protecting this code by an is_debug() check, because if we do,
|
||||
// some weird compiler bug appears and somehow makes the quality always 0.
|
||||
const char *pbuffertext = pbuffer_supported ? " (pbuffer)" : "";
|
||||
const char *pixmaptext = pixmap_supported ? " (pixmap)" : "";
|
||||
const char *slowtext = slow ? " (slow)" : "";
|
||||
androiddisplay_cat.debug()
|
||||
<< i << ": " << fbprops << pbuffertext << pixmaptext << slowtext << "\n";
|
||||
int quality = fbprops.get_quality(properties);
|
||||
if ((quality > 0)&&(slow)) quality -= 10000000;
|
||||
|
||||
if (need_pbuffer && !pbuffer_supported) {
|
||||
continue;
|
||||
}
|
||||
if (need_pixmap && !pixmap_supported) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (quality > best_quality) {
|
||||
best_quality = quality;
|
||||
best_result = i;
|
||||
best_props = fbprops;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_quality > 0) {
|
||||
androiddisplay_cat.debug()
|
||||
<< "Chosen config " << best_result << ": " << best_props << "\n";
|
||||
_fbconfig = configs[best_result];
|
||||
eglGetConfigAttrib(_egl_display, _fbconfig, EGL_NATIVE_VISUAL_ID, &_format);
|
||||
|
||||
androiddisplay_cat.debug()
|
||||
<< "Window format: " << _format << "\n";
|
||||
|
||||
_fbprops = best_props;
|
||||
return;
|
||||
}
|
||||
|
||||
androiddisplay_cat.error() <<
|
||||
"Could not find a usable pixel format.\n";
|
||||
|
||||
delete[] configs;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::create_context
|
||||
// Access: Private
|
||||
// Description: Creates the context based on the config previously
|
||||
// obtained in choose_pixel_format.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AndroidGraphicsStateGuardian::
|
||||
create_context() {
|
||||
if (_context != EGL_NO_CONTEXT) {
|
||||
destroy_context();
|
||||
}
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
_context = eglCreateContext(_egl_display, _fbconfig, _share_context, context_attribs);
|
||||
#else
|
||||
_context = eglCreateContext(_egl_display, _fbconfig, _share_context, NULL);
|
||||
#endif
|
||||
|
||||
int err = eglGetError();
|
||||
if (_context != EGL_NO_CONTEXT && err == EGL_SUCCESS) {
|
||||
_needs_reset = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
androiddisplay_cat.error()
|
||||
<< "Could not create EGL context!\n"
|
||||
<< get_egl_error_string(err) << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::destroy_context
|
||||
// Access: Private
|
||||
// Description: Destroys the context previously created by
|
||||
// create_context.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsStateGuardian::
|
||||
destroy_context() {
|
||||
if (_context == EGL_NO_CONTEXT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
|
||||
androiddisplay_cat.error() << "Failed to call eglMakeCurrent: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
|
||||
release_all();
|
||||
|
||||
eglDestroyContext(_egl_display, _context);
|
||||
_context = EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::reset
|
||||
// Access: Public, Virtual
|
||||
// Description: Resets all internal state as if the gsg were newly
|
||||
// created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsStateGuardian::
|
||||
reset() {
|
||||
#ifdef OPENGLES_2
|
||||
GLES2GraphicsStateGuardian::reset();
|
||||
#else
|
||||
GLESGraphicsStateGuardian::reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::egl_is_at_least_version
|
||||
// Access: Public
|
||||
// Description: Returns true if the runtime GLX version number is at
|
||||
// least the indicated value, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AndroidGraphicsStateGuardian::
|
||||
egl_is_at_least_version(int major_version, int minor_version) const {
|
||||
if (_egl_version_major < major_version) {
|
||||
return false;
|
||||
}
|
||||
if (_egl_version_minor < minor_version) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::gl_flush
|
||||
// Access: Protected, Virtual
|
||||
// Description: Calls glFlush().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsStateGuardian::
|
||||
gl_flush() const {
|
||||
#ifdef OPENGLES_2
|
||||
GLES2GraphicsStateGuardian::gl_flush();
|
||||
#else
|
||||
GLESGraphicsStateGuardian::gl_flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::gl_get_error
|
||||
// Access: Protected, Virtual
|
||||
// Description: Returns the result of glGetError().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GLenum AndroidGraphicsStateGuardian::
|
||||
gl_get_error() const {
|
||||
#ifdef OPENGLES_2
|
||||
return GLES2GraphicsStateGuardian::gl_get_error();
|
||||
#else
|
||||
return GLESGraphicsStateGuardian::gl_get_error();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::query_gl_version
|
||||
// Access: Protected, Virtual
|
||||
// Description: Queries the runtime version of OpenGL in use.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsStateGuardian::
|
||||
query_gl_version() {
|
||||
#ifdef OPENGLES_2
|
||||
GLES2GraphicsStateGuardian::query_gl_version();
|
||||
#else
|
||||
GLESGraphicsStateGuardian::query_gl_version();
|
||||
#endif
|
||||
|
||||
// Calling eglInitialize on an already-initialized display will
|
||||
// just provide us the version numbers.
|
||||
if (!eglInitialize(_egl_display, &_egl_version_major, &_egl_version_minor)) {
|
||||
androiddisplay_cat.error() << "Failed to get EGL version number: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
|
||||
// We output to glesgsg_cat instead of androiddisplay_cat, since this is
|
||||
// where the GL version has been output, and it's nice to see the
|
||||
// two of these together.
|
||||
#ifdef OPENGLES_2
|
||||
if (gles2gsg_cat.is_debug()) {
|
||||
gles2gsg_cat.debug()
|
||||
#else
|
||||
if (glesgsg_cat.is_debug()) {
|
||||
glesgsg_cat.debug()
|
||||
#endif
|
||||
<< "EGL_VERSION = " << _egl_version_major << "." << _egl_version_minor
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::get_extra_extensions
|
||||
// Access: Protected, Virtual
|
||||
// Description: This may be redefined by a derived class (e.g. glx or
|
||||
// wgl) to get whatever further extensions strings may
|
||||
// be appropriate to that interface, in addition to the
|
||||
// GL extension strings return by glGetString().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsStateGuardian::
|
||||
get_extra_extensions() {
|
||||
save_extensions(eglQueryString(_egl_display, EGL_EXTENSIONS));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsStateGuardian::do_get_extension_func
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the pointer to the GL extension function with
|
||||
// the indicated name. It is the responsibility of the
|
||||
// caller to ensure that the required extension is
|
||||
// defined in the OpenGL runtime prior to calling this;
|
||||
// it is an error to call this for a function that is
|
||||
// not defined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void *AndroidGraphicsStateGuardian::
|
||||
do_get_extension_func(const char *prefix, const char *name) {
|
||||
string fullname = string(prefix) + string(name);
|
||||
|
||||
return (void *)eglGetProcAddress(fullname.c_str());
|
||||
}
|
97
panda/src/androiddisplay/androidGraphicsStateGuardian.h
Normal file
97
panda/src/androiddisplay/androidGraphicsStateGuardian.h
Normal file
@ -0,0 +1,97 @@
|
||||
// Filename: androidGraphicsStateGuardian.h
|
||||
// Created by: pro-rsoft (21May09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ANDROIDGRAPHICSSTATEGUARDIAN_H
|
||||
#define ANDROIDGRAPHICSSTATEGUARDIAN_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "androidGraphicsPipe.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AndroidGraphicsStateGuardian
|
||||
// Description : A tiny specialization on GLESGraphicsStateGuardian
|
||||
// to add some egl-specific information.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef OPENGLES_2
|
||||
class AndroidGraphicsStateGuardian : public GLES2GraphicsStateGuardian {
|
||||
#else
|
||||
class AndroidGraphicsStateGuardian : public GLESGraphicsStateGuardian {
|
||||
#endif
|
||||
public:
|
||||
INLINE const FrameBufferProperties &get_fb_properties() const;
|
||||
void get_properties(FrameBufferProperties &properties,
|
||||
bool &pbuffer_supported, bool &pixmap_supported,
|
||||
bool &slow, EGLConfig config);
|
||||
void choose_pixel_format(const FrameBufferProperties &properties,
|
||||
bool need_pbuffer, bool need_pixmap);
|
||||
bool create_context();
|
||||
void destroy_context();
|
||||
|
||||
AndroidGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
AndroidGraphicsStateGuardian *share_with);
|
||||
|
||||
virtual ~AndroidGraphicsStateGuardian();
|
||||
|
||||
virtual void reset();
|
||||
|
||||
bool egl_is_at_least_version(int major_version, int minor_version) const;
|
||||
|
||||
protected:
|
||||
EGLContext _share_context;
|
||||
EGLContext _context;
|
||||
EGLDisplay _egl_display;
|
||||
EGLConfig _fbconfig;
|
||||
EGLint _format;
|
||||
FrameBufferProperties _fbprops;
|
||||
|
||||
protected:
|
||||
virtual void gl_flush() const;
|
||||
virtual GLenum gl_get_error() const;
|
||||
|
||||
virtual void query_gl_version();
|
||||
virtual void get_extra_extensions();
|
||||
virtual void *do_get_extension_func(const char *prefix, const char *name);
|
||||
|
||||
private:
|
||||
int _egl_version_major, _egl_version_minor;
|
||||
|
||||
friend class AndroidGraphicsWindow;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
#ifdef OPENGLES_2
|
||||
GLES2GraphicsStateGuardian::init_type();
|
||||
register_type(_type_handle, "AndroidGraphicsStateGuardian",
|
||||
GLES2GraphicsStateGuardian::get_class_type());
|
||||
#else
|
||||
GLESGraphicsStateGuardian::init_type();
|
||||
register_type(_type_handle, "AndroidGraphicsStateGuardian",
|
||||
GLESGraphicsStateGuardian::get_class_type());
|
||||
#endif
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "androidGraphicsStateGuardian.I"
|
||||
|
||||
#endif
|
14
panda/src/androiddisplay/androidGraphicsWindow.I
Normal file
14
panda/src/androiddisplay/androidGraphicsWindow.I
Normal file
@ -0,0 +1,14 @@
|
||||
// Filename: androidGraphicsWindow.I
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
771
panda/src/androiddisplay/androidGraphicsWindow.cxx
Normal file
771
panda/src/androiddisplay/androidGraphicsWindow.cxx
Normal file
@ -0,0 +1,771 @@
|
||||
// Filename: androidGraphicsWindow.cxx
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "androidGraphicsWindow.h"
|
||||
#include "androidGraphicsStateGuardian.h"
|
||||
#include "config_androiddisplay.h"
|
||||
#include "androidGraphicsPipe.h"
|
||||
|
||||
#include "graphicsPipe.h"
|
||||
#include "keyboardButton.h"
|
||||
#include "mouseButton.h"
|
||||
#include "clockObject.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "textEncoder.h"
|
||||
#include "throw_event.h"
|
||||
#include "nativeWindowHandle.h"
|
||||
|
||||
#include "android_native_app_glue.h"
|
||||
#include <android/window.h>
|
||||
#include <android/log.h>
|
||||
|
||||
extern struct android_app* panda_android_app;
|
||||
|
||||
TypeHandle AndroidGraphicsWindow::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AndroidGraphicsWindow::
|
||||
AndroidGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host) :
|
||||
GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
|
||||
{
|
||||
AndroidGraphicsPipe *android_pipe;
|
||||
DCAST_INTO_V(android_pipe, _pipe);
|
||||
|
||||
_egl_display = android_pipe->_egl_display;
|
||||
_egl_surface = 0;
|
||||
|
||||
_app = panda_android_app;
|
||||
|
||||
GraphicsWindowInputDevice device =
|
||||
GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
|
||||
add_input_device(device);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AndroidGraphicsWindow::
|
||||
~AndroidGraphicsWindow() {
|
||||
destroy_surface();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::begin_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// before beginning rendering for a given frame. It
|
||||
// should do whatever setup is required, and return true
|
||||
// if the frame should be rendered, or false if it
|
||||
// should be skipped.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AndroidGraphicsWindow::
|
||||
begin_frame(FrameMode mode, Thread *current_thread) {
|
||||
PStatTimer timer(_make_current_pcollector, current_thread);
|
||||
|
||||
begin_frame_spam(mode);
|
||||
if (_gsg == (GraphicsStateGuardian *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//XXX not open yet.
|
||||
if (_egl_surface == EGL_NO_SURFACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AndroidGraphicsStateGuardian *androidgsg;
|
||||
DCAST_INTO_R(androidgsg, _gsg, false);
|
||||
{
|
||||
if (eglGetCurrentDisplay() == _egl_display &&
|
||||
eglGetCurrentSurface(EGL_READ) == _egl_surface &&
|
||||
eglGetCurrentSurface(EGL_DRAW) == _egl_surface &&
|
||||
eglGetCurrentContext() == androidgsg->_context) {
|
||||
// No need to make the context current again. Short-circuit
|
||||
// this possibly-expensive call.
|
||||
} else {
|
||||
// Need to set the context.
|
||||
if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, androidgsg->_context)) {
|
||||
androiddisplay_cat.error() << "Failed to call eglMakeCurrent: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have made the context current to a window, we can
|
||||
// reset the GSG state if this is the first time it has been used.
|
||||
// (We can't just call reset() when we construct the GSG, because
|
||||
// reset() requires having a current context.)
|
||||
androidgsg->reset_if_new();
|
||||
|
||||
if (mode == FM_render) {
|
||||
// begin_render_texture();
|
||||
clear_cube_map_selection();
|
||||
}
|
||||
|
||||
_gsg->set_current_properties(&get_fb_properties());
|
||||
return _gsg->begin_frame(current_thread);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::end_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// after rendering is completed for a given frame. It
|
||||
// should do whatever finalization is required.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsWindow::
|
||||
end_frame(FrameMode mode, Thread *current_thread) {
|
||||
end_frame_spam(mode);
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
|
||||
if (mode == FM_render) {
|
||||
// end_render_texture();
|
||||
copy_to_textures();
|
||||
}
|
||||
|
||||
_gsg->end_frame(current_thread);
|
||||
|
||||
if (mode == FM_render) {
|
||||
trigger_flip();
|
||||
clear_cube_map_selection();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::end_flip
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// after begin_flip() has been called on all windows, to
|
||||
// finish the exchange of the front and back buffers.
|
||||
//
|
||||
// This should cause the window to wait for the flip, if
|
||||
// necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsWindow::
|
||||
end_flip() {
|
||||
if (_gsg != (GraphicsStateGuardian *)NULL && _flip_ready) {
|
||||
|
||||
// It doesn't appear to be necessary to ensure the graphics
|
||||
// context is current before flipping the windows, and insisting
|
||||
// on doing so can be a significant performance hit.
|
||||
|
||||
//make_current();
|
||||
|
||||
if (_egl_surface != EGL_NO_SURFACE) {
|
||||
eglSwapBuffers(_egl_display, _egl_surface);
|
||||
}
|
||||
}
|
||||
GraphicsWindow::end_flip();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::process_events
|
||||
// Access: Public, Virtual
|
||||
// Description: Do whatever processing is necessary to ensure that
|
||||
// the window responds to user events. Also, honor any
|
||||
// requests recently made via request_properties()
|
||||
//
|
||||
// This function is called only within the window
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsWindow::
|
||||
process_events() {
|
||||
GraphicsWindow::process_events();
|
||||
|
||||
// Read all pending events.
|
||||
int looper_id;
|
||||
int events;
|
||||
struct android_poll_source* source;
|
||||
|
||||
// Loop until all events are read.
|
||||
while ((looper_id = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) {
|
||||
// Process this event.
|
||||
if (source != NULL) {
|
||||
source->process(_app, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::set_properties_now
|
||||
// Access: Public, Virtual
|
||||
// Description: Applies the requested set of properties to the
|
||||
// window, if possible, for instance to request a change
|
||||
// in size or minimization status.
|
||||
//
|
||||
// The window properties are applied immediately, rather
|
||||
// than waiting until the next frame. This implies that
|
||||
// this method may *only* be called from within the
|
||||
// window thread.
|
||||
//
|
||||
// The return value is true if the properties are set,
|
||||
// false if they are ignored. This is mainly useful for
|
||||
// derived classes to implement extensions to this
|
||||
// function.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsWindow::
|
||||
set_properties_now(WindowProperties &properties) {
|
||||
if (_pipe == (GraphicsPipe *)NULL) {
|
||||
// If the pipe is null, we're probably closing down.
|
||||
GraphicsWindow::set_properties_now(properties);
|
||||
return;
|
||||
}
|
||||
|
||||
GraphicsWindow::set_properties_now(properties);
|
||||
if (!properties.is_any_specified()) {
|
||||
// The base class has already handled this case.
|
||||
return;
|
||||
}
|
||||
|
||||
// There's not really much we can change on Android.
|
||||
if (properties.has_fullscreen()) {
|
||||
uint32_t add_flags = 0;
|
||||
uint32_t del_flags = 0;
|
||||
if (_properties.get_fullscreen()) {
|
||||
add_flags |= AWINDOW_FLAG_FULLSCREEN;
|
||||
} else {
|
||||
del_flags |= AWINDOW_FLAG_FULLSCREEN;
|
||||
}
|
||||
ANativeActivity_setWindowFlags(_app->activity, add_flags, del_flags);
|
||||
|
||||
_properties.set_fullscreen(properties.get_fullscreen());
|
||||
properties.clear_fullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::close_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: Closes the window right now. Called from the window
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsWindow::
|
||||
close_window() {
|
||||
destroy_surface();
|
||||
|
||||
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
||||
_gsg.clear();
|
||||
}
|
||||
|
||||
GraphicsWindow::close_window();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::open_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: Opens the window right now. Called from the window
|
||||
// thread. Returns true if the window is successfully
|
||||
// opened, or false if there was a problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AndroidGraphicsWindow::
|
||||
open_window() {
|
||||
// GSG Creation/Initialization
|
||||
AndroidGraphicsStateGuardian *androidgsg;
|
||||
if (_gsg == 0) {
|
||||
// There is no old gsg. Create a new one.
|
||||
androidgsg = new AndroidGraphicsStateGuardian(_engine, _pipe, NULL);
|
||||
androidgsg->choose_pixel_format(_fb_properties, false, false);
|
||||
_gsg = androidgsg;
|
||||
} else {
|
||||
// If the old gsg has the wrong pixel format, create a
|
||||
// new one that shares with the old gsg.
|
||||
DCAST_INTO_R(androidgsg, _gsg, false);
|
||||
if (!androidgsg->get_fb_properties().subsumes(_fb_properties)) {
|
||||
androidgsg = new AndroidGraphicsStateGuardian(_engine, _pipe, androidgsg);
|
||||
androidgsg->choose_pixel_format(_fb_properties, false, false);
|
||||
_gsg = androidgsg;
|
||||
}
|
||||
}
|
||||
|
||||
// Register the callbacks
|
||||
assert(_app != NULL);
|
||||
_app->userData = this;
|
||||
_app->onAppCmd = handle_command;
|
||||
_app->onInputEvent = handle_input_event;
|
||||
|
||||
// Wait until Android has opened the window.
|
||||
while (_app->window == NULL) {
|
||||
process_events();
|
||||
}
|
||||
|
||||
// create_surface should have been called by now.
|
||||
if (_egl_surface == EGL_NO_SURFACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set some other properties.
|
||||
_properties.set_origin(0, 0);
|
||||
_properties.set_cursor_hidden(true);
|
||||
_properties.set_undecorated(true);
|
||||
|
||||
if (!androidgsg->get_fb_properties().verify_hardware_software
|
||||
(_fb_properties, androidgsg->get_gl_renderer())) {
|
||||
close_window();
|
||||
return false;
|
||||
}
|
||||
|
||||
//_fb_properties = androidgsg->get_fb_properties();
|
||||
|
||||
androiddisplay_cat.error() << "open_window done\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::destroy_surface
|
||||
// Access: Protected, Virtual
|
||||
// Description: Terminates the EGL surface.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsWindow::
|
||||
destroy_surface() {
|
||||
if (_egl_surface != EGL_NO_SURFACE) {
|
||||
if (!eglDestroySurface(_egl_display, _egl_surface)) {
|
||||
androiddisplay_cat.error() << "Failed to destroy surface: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
_egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
// Destroy the current context.
|
||||
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
||||
AndroidGraphicsStateGuardian *androidgsg;
|
||||
DCAST_INTO_V(androidgsg, _gsg);
|
||||
androidgsg->destroy_context();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::create_surface
|
||||
// Access: Protected, Virtual
|
||||
// Description: Creates the EGL surface.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AndroidGraphicsWindow::
|
||||
create_surface() {
|
||||
AndroidGraphicsStateGuardian *androidgsg;
|
||||
DCAST_INTO_R(androidgsg, _gsg, false);
|
||||
|
||||
// Reconfigure the window buffers to match that of our framebuffer config.
|
||||
ANativeWindow_setBuffersGeometry(_app->window, 0, 0, androidgsg->_format);
|
||||
|
||||
// Set any window flags
|
||||
uint32_t add_flags = 0;
|
||||
uint32_t del_flags = 0;
|
||||
if (_properties.get_fullscreen()) {
|
||||
add_flags |= AWINDOW_FLAG_FULLSCREEN;
|
||||
} else {
|
||||
del_flags |= AWINDOW_FLAG_FULLSCREEN;
|
||||
}
|
||||
ANativeActivity_setWindowFlags(_app->activity, add_flags, del_flags);
|
||||
|
||||
// Create the EGL surface.
|
||||
_egl_surface = eglCreateWindowSurface(_egl_display, androidgsg->_fbconfig, _app->window, NULL);
|
||||
if (eglGetError() != EGL_SUCCESS) {
|
||||
androiddisplay_cat.error()
|
||||
<< "Failed to create window surface.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a context.
|
||||
if (androidgsg->_context == EGL_NO_CONTEXT) {
|
||||
androiddisplay_cat.error() << "creating context\n";
|
||||
if (!androidgsg->create_context()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to our newly created context.
|
||||
if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, androidgsg->_context)) {
|
||||
androiddisplay_cat.error() << "Failed to call eglMakeCurrent: "
|
||||
<< get_egl_error_string(eglGetError()) << "\n";
|
||||
}
|
||||
|
||||
// Query the size of the surface.
|
||||
//EGLint width, height;
|
||||
//eglQuerySurface(_egl_display, _egl_surface, EGL_WIDTH, &width);
|
||||
//eglQuerySurface(_egl_display, _egl_surface, EGL_HEIGHT, &height);
|
||||
|
||||
androidgsg->reset_if_new();
|
||||
if (!androidgsg->is_valid()) {
|
||||
close_window();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::handle_command
|
||||
// Access: Private, Static
|
||||
// Description: Android app sends a command from the main thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsWindow::
|
||||
handle_command(struct android_app *app, int32_t command) {
|
||||
AndroidGraphicsWindow* window = (AndroidGraphicsWindow*) app->userData;
|
||||
window->ns_handle_command(command);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::ns_handle_command
|
||||
// Access: Private
|
||||
// Description: Android app sends a command from the main thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AndroidGraphicsWindow::
|
||||
ns_handle_command(int32_t command) {
|
||||
WindowProperties properties;
|
||||
|
||||
switch (command) {
|
||||
case APP_CMD_SAVE_STATE:
|
||||
// The system has asked us to save our current state. Do so.
|
||||
//engine->app->savedState = malloc(sizeof(struct saved_state));
|
||||
//*((struct saved_state*)engine->app->savedState) = engine->state;
|
||||
//engine->app->savedStateSize = sizeof(struct saved_state);
|
||||
break;
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
// The window is being shown, get it ready.
|
||||
if (_app->window != NULL) {
|
||||
create_surface();
|
||||
properties.set_minimized(false);
|
||||
system_changed_properties(properties);
|
||||
}
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
destroy_surface();
|
||||
properties.set_minimized(true);
|
||||
system_changed_properties(properties);
|
||||
break;
|
||||
case APP_CMD_WINDOW_RESIZED:
|
||||
break;
|
||||
case APP_CMD_WINDOW_REDRAW_NEEDED:
|
||||
break;
|
||||
case APP_CMD_CONTENT_RECT_CHANGED:
|
||||
properties.set_origin(_app->contentRect.left, _app->contentRect.top);
|
||||
properties.set_size(_app->contentRect.right - _app->contentRect.left,
|
||||
_app->contentRect.bottom - _app->contentRect.top);
|
||||
system_changed_properties(properties);
|
||||
break;
|
||||
case APP_CMD_GAINED_FOCUS:
|
||||
properties.set_foreground(true);
|
||||
system_changed_properties(properties);
|
||||
break;
|
||||
case APP_CMD_LOST_FOCUS:
|
||||
properties.set_foreground(false);
|
||||
system_changed_properties(properties);
|
||||
break;
|
||||
case APP_CMD_DESTROY:
|
||||
close_window();
|
||||
properties.set_open(false);
|
||||
system_changed_properties(properties);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::handle_input_event
|
||||
// Access: Private, Static
|
||||
// Description: Processes an input event. Returns 1 if the event
|
||||
// was handled, 0 otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int32_t AndroidGraphicsWindow::
|
||||
handle_input_event(struct android_app* app, AInputEvent *event) {
|
||||
AndroidGraphicsWindow* window = (AndroidGraphicsWindow*) app->userData;
|
||||
|
||||
int32_t event_type = AInputEvent_getType(event);
|
||||
switch (event_type) {
|
||||
case AINPUT_EVENT_TYPE_KEY:
|
||||
return window->handle_key_event(event);
|
||||
case AINPUT_EVENT_TYPE_MOTION:
|
||||
return window->handle_motion_event(event);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::handle_keystroke
|
||||
// Access: Private
|
||||
// Description: Processes a key event.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int32_t AndroidGraphicsWindow::
|
||||
handle_key_event(const AInputEvent *event) {
|
||||
/*
|
||||
int32_t meta = AKeyEvent_getMetaState(event);
|
||||
if (meta | AMETA_ALT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.alt());
|
||||
}
|
||||
if (meta | AMETA_ALT_LEFT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.lalt());
|
||||
}
|
||||
if (meta | AMETA_ALT_RIGHT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.ralt());
|
||||
}
|
||||
if (meta | AMETA_SHIFT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.shift());
|
||||
}
|
||||
if (meta | AMETA_SHIFT_LEFT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.lshift());
|
||||
}
|
||||
if (meta | AMETA_SHIFT_RIGHT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.rshift());
|
||||
}*/
|
||||
|
||||
int32_t keycode = AKeyEvent_getKeyCode(event);
|
||||
ButtonHandle button = map_button(keycode);
|
||||
|
||||
if (button == ButtonHandle::none()) {
|
||||
androiddisplay_cat.warning()
|
||||
<< "Unknown keycode: " << keycode << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is it an up or down event?
|
||||
int32_t action = AKeyEvent_getAction(event);
|
||||
if (action == AKEY_EVENT_ACTION_DOWN) {
|
||||
_input_devices[0].button_down(button);
|
||||
} else if (action == AKEY_EVENT_ACTION_UP) {
|
||||
_input_devices[0].button_up(button);
|
||||
}
|
||||
//TODO getRepeatCount, ACTION_MULTIPLE
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::handle_motion_event
|
||||
// Access: Private
|
||||
// Description: Processes a motion event.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int32_t AndroidGraphicsWindow::
|
||||
handle_motion_event(const AInputEvent *event) {
|
||||
int32_t action = AMotionEvent_getAction(event);
|
||||
action &= AMOTION_EVENT_ACTION_MASK;
|
||||
|
||||
if (action == AMOTION_EVENT_ACTION_DOWN) {
|
||||
_input_devices[0].button_down(MouseButton::one());
|
||||
} else if (action == AMOTION_EVENT_ACTION_UP) {
|
||||
_input_devices[0].button_up(MouseButton::one());
|
||||
}
|
||||
|
||||
float x = AMotionEvent_getX(event, 0);
|
||||
float y = AMotionEvent_getY(event, 0);
|
||||
|
||||
_input_devices[0].set_pointer_in_window(x, y);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AndroidGraphicsWindow::map_button
|
||||
// Access: Private
|
||||
// Description: Given an Android keycode, returns an appropriate
|
||||
// ButtonHandle object, or ButtonHandle::none() if
|
||||
// a matching ButtonHandle does not exist.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ButtonHandle AndroidGraphicsWindow::
|
||||
map_button(int32_t keycode) {
|
||||
switch (keycode) {
|
||||
case AKEYCODE_SOFT_LEFT:
|
||||
case AKEYCODE_SOFT_RIGHT:
|
||||
case AKEYCODE_HOME:
|
||||
case AKEYCODE_BACK:
|
||||
case AKEYCODE_CALL:
|
||||
case AKEYCODE_ENDCALL:
|
||||
break;
|
||||
case AKEYCODE_0:
|
||||
return KeyboardButton::ascii_key('0');
|
||||
case AKEYCODE_1:
|
||||
return KeyboardButton::ascii_key('1');
|
||||
case AKEYCODE_2:
|
||||
return KeyboardButton::ascii_key('2');
|
||||
case AKEYCODE_3:
|
||||
return KeyboardButton::ascii_key('3');
|
||||
case AKEYCODE_4:
|
||||
return KeyboardButton::ascii_key('4');
|
||||
case AKEYCODE_5:
|
||||
return KeyboardButton::ascii_key('5');
|
||||
case AKEYCODE_6:
|
||||
return KeyboardButton::ascii_key('6');
|
||||
case AKEYCODE_7:
|
||||
return KeyboardButton::ascii_key('7');
|
||||
case AKEYCODE_8:
|
||||
return KeyboardButton::ascii_key('8');
|
||||
case AKEYCODE_9:
|
||||
return KeyboardButton::ascii_key('9');
|
||||
case AKEYCODE_STAR:
|
||||
return KeyboardButton::ascii_key('*');
|
||||
case AKEYCODE_POUND:
|
||||
return KeyboardButton::ascii_key('#');
|
||||
case AKEYCODE_DPAD_UP:
|
||||
return KeyboardButton::up();
|
||||
case AKEYCODE_DPAD_DOWN:
|
||||
return KeyboardButton::down();
|
||||
case AKEYCODE_DPAD_LEFT:
|
||||
return KeyboardButton::left();
|
||||
case AKEYCODE_DPAD_RIGHT:
|
||||
return KeyboardButton::right();
|
||||
case AKEYCODE_DPAD_CENTER:
|
||||
case AKEYCODE_VOLUME_UP:
|
||||
case AKEYCODE_VOLUME_DOWN:
|
||||
case AKEYCODE_POWER:
|
||||
case AKEYCODE_CAMERA:
|
||||
case AKEYCODE_CLEAR:
|
||||
break;
|
||||
case AKEYCODE_A:
|
||||
return KeyboardButton::ascii_key('a');
|
||||
case AKEYCODE_B:
|
||||
return KeyboardButton::ascii_key('b');
|
||||
case AKEYCODE_C:
|
||||
return KeyboardButton::ascii_key('c');
|
||||
case AKEYCODE_D:
|
||||
return KeyboardButton::ascii_key('d');
|
||||
case AKEYCODE_E:
|
||||
return KeyboardButton::ascii_key('e');
|
||||
case AKEYCODE_F:
|
||||
return KeyboardButton::ascii_key('f');
|
||||
case AKEYCODE_G:
|
||||
return KeyboardButton::ascii_key('g');
|
||||
case AKEYCODE_H:
|
||||
return KeyboardButton::ascii_key('h');
|
||||
case AKEYCODE_I:
|
||||
return KeyboardButton::ascii_key('i');
|
||||
case AKEYCODE_J:
|
||||
return KeyboardButton::ascii_key('j');
|
||||
case AKEYCODE_K:
|
||||
return KeyboardButton::ascii_key('k');
|
||||
case AKEYCODE_L:
|
||||
return KeyboardButton::ascii_key('l');
|
||||
case AKEYCODE_M:
|
||||
return KeyboardButton::ascii_key('m');
|
||||
case AKEYCODE_N:
|
||||
return KeyboardButton::ascii_key('n');
|
||||
case AKEYCODE_O:
|
||||
return KeyboardButton::ascii_key('o');
|
||||
case AKEYCODE_P:
|
||||
return KeyboardButton::ascii_key('p');
|
||||
case AKEYCODE_Q:
|
||||
return KeyboardButton::ascii_key('q');
|
||||
case AKEYCODE_R:
|
||||
return KeyboardButton::ascii_key('r');
|
||||
case AKEYCODE_S:
|
||||
return KeyboardButton::ascii_key('s');
|
||||
case AKEYCODE_T:
|
||||
return KeyboardButton::ascii_key('t');
|
||||
case AKEYCODE_U:
|
||||
return KeyboardButton::ascii_key('u');
|
||||
case AKEYCODE_V:
|
||||
return KeyboardButton::ascii_key('v');
|
||||
case AKEYCODE_W:
|
||||
return KeyboardButton::ascii_key('w');
|
||||
case AKEYCODE_X:
|
||||
return KeyboardButton::ascii_key('x');
|
||||
case AKEYCODE_Y:
|
||||
return KeyboardButton::ascii_key('y');
|
||||
case AKEYCODE_Z:
|
||||
return KeyboardButton::ascii_key('z');
|
||||
case AKEYCODE_COMMA:
|
||||
return KeyboardButton::ascii_key(',');
|
||||
case AKEYCODE_PERIOD:
|
||||
return KeyboardButton::ascii_key('.');
|
||||
case AKEYCODE_ALT_LEFT:
|
||||
return KeyboardButton::lalt();
|
||||
case AKEYCODE_ALT_RIGHT:
|
||||
return KeyboardButton::ralt();
|
||||
case AKEYCODE_SHIFT_LEFT:
|
||||
return KeyboardButton::lshift();
|
||||
case AKEYCODE_SHIFT_RIGHT:
|
||||
return KeyboardButton::rshift();
|
||||
case AKEYCODE_TAB:
|
||||
return KeyboardButton::tab();
|
||||
case AKEYCODE_SPACE:
|
||||
return KeyboardButton::space();
|
||||
case AKEYCODE_SYM:
|
||||
case AKEYCODE_EXPLORER:
|
||||
case AKEYCODE_ENVELOPE:
|
||||
break;
|
||||
case AKEYCODE_ENTER:
|
||||
return KeyboardButton::enter();
|
||||
case AKEYCODE_DEL:
|
||||
return KeyboardButton::del();
|
||||
case AKEYCODE_GRAVE:
|
||||
return KeyboardButton::ascii_key('`');
|
||||
case AKEYCODE_MINUS:
|
||||
return KeyboardButton::ascii_key('-');
|
||||
case AKEYCODE_EQUALS:
|
||||
return KeyboardButton::ascii_key('=');
|
||||
case AKEYCODE_LEFT_BRACKET:
|
||||
return KeyboardButton::ascii_key('[');
|
||||
case AKEYCODE_RIGHT_BRACKET:
|
||||
return KeyboardButton::ascii_key(']');
|
||||
case AKEYCODE_BACKSLASH:
|
||||
return KeyboardButton::ascii_key('\\');
|
||||
case AKEYCODE_SEMICOLON:
|
||||
return KeyboardButton::ascii_key(';');
|
||||
case AKEYCODE_APOSTROPHE:
|
||||
return KeyboardButton::ascii_key('\'');
|
||||
case AKEYCODE_SLASH:
|
||||
return KeyboardButton::ascii_key('/');
|
||||
case AKEYCODE_AT:
|
||||
return KeyboardButton::ascii_key('@');
|
||||
case AKEYCODE_NUM:
|
||||
case AKEYCODE_HEADSETHOOK:
|
||||
case AKEYCODE_FOCUS:
|
||||
break;
|
||||
case AKEYCODE_PLUS:
|
||||
return KeyboardButton::ascii_key('+');
|
||||
case AKEYCODE_MENU:
|
||||
case AKEYCODE_NOTIFICATION:
|
||||
case AKEYCODE_SEARCH:
|
||||
case AKEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case AKEYCODE_MEDIA_STOP:
|
||||
case AKEYCODE_MEDIA_NEXT:
|
||||
case AKEYCODE_MEDIA_PREVIOUS:
|
||||
case AKEYCODE_MEDIA_REWIND:
|
||||
case AKEYCODE_MEDIA_FAST_FORWARD:
|
||||
case AKEYCODE_MUTE:
|
||||
break;
|
||||
case AKEYCODE_PAGE_UP:
|
||||
return KeyboardButton::page_up();
|
||||
case AKEYCODE_PAGE_DOWN:
|
||||
return KeyboardButton::page_down();
|
||||
case AKEYCODE_PICTSYMBOLS:
|
||||
case AKEYCODE_SWITCH_CHARSET:
|
||||
case AKEYCODE_BUTTON_A:
|
||||
case AKEYCODE_BUTTON_B:
|
||||
case AKEYCODE_BUTTON_C:
|
||||
case AKEYCODE_BUTTON_X:
|
||||
case AKEYCODE_BUTTON_Y:
|
||||
case AKEYCODE_BUTTON_Z:
|
||||
case AKEYCODE_BUTTON_L1:
|
||||
case AKEYCODE_BUTTON_R1:
|
||||
case AKEYCODE_BUTTON_L2:
|
||||
case AKEYCODE_BUTTON_R2:
|
||||
case AKEYCODE_BUTTON_THUMBL:
|
||||
case AKEYCODE_BUTTON_THUMBR:
|
||||
case AKEYCODE_BUTTON_START:
|
||||
case AKEYCODE_BUTTON_SELECT:
|
||||
case AKEYCODE_BUTTON_MODE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ButtonHandle::none();
|
||||
}
|
99
panda/src/androiddisplay/androidGraphicsWindow.h
Normal file
99
panda/src/androiddisplay/androidGraphicsWindow.h
Normal file
@ -0,0 +1,99 @@
|
||||
// Filename: androidGraphicsWindow.h
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ANDROIDGRAPHICSWINDOW_H
|
||||
#define ANDROIDGRAPHICSWINDOW_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "androidGraphicsPipe.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "buttonHandle.h"
|
||||
|
||||
#include <android/native_window.h>
|
||||
#include <android/input.h>
|
||||
#include <android/native_activity.h>
|
||||
#include <android/rect.h>
|
||||
|
||||
struct android_app;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AndroidGraphicsWindow
|
||||
// Description : An interface to manage Android windows and their
|
||||
// appropriate EGL surfaces.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class AndroidGraphicsWindow : public GraphicsWindow {
|
||||
public:
|
||||
AndroidGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host);
|
||||
virtual ~AndroidGraphicsWindow();
|
||||
|
||||
virtual bool begin_frame(FrameMode mode, Thread *current_thread);
|
||||
virtual void end_frame(FrameMode mode, Thread *current_thread);
|
||||
virtual void end_flip();
|
||||
|
||||
virtual void process_events();
|
||||
virtual void set_properties_now(WindowProperties &properties);
|
||||
|
||||
protected:
|
||||
virtual void close_window();
|
||||
virtual bool open_window();
|
||||
|
||||
virtual void destroy_surface();
|
||||
virtual bool create_surface();
|
||||
|
||||
private:
|
||||
static void handle_command(struct android_app *app, int32_t command);
|
||||
static int32_t handle_input_event(struct android_app *app, AInputEvent *event);
|
||||
|
||||
void ns_handle_command(int32_t command);
|
||||
int32_t handle_key_event(const AInputEvent *event);
|
||||
int32_t handle_motion_event(const AInputEvent *event);
|
||||
|
||||
ButtonHandle map_button(int32_t keycode);
|
||||
|
||||
private:
|
||||
struct android_app* _app;
|
||||
|
||||
EGLDisplay _egl_display;
|
||||
EGLSurface _egl_surface;
|
||||
|
||||
const ARect *rect;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
GraphicsWindow::init_type();
|
||||
register_type(_type_handle, "AndroidGraphicsWindow",
|
||||
GraphicsWindow::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "androidGraphicsWindow.I"
|
||||
|
||||
#endif
|
90
panda/src/androiddisplay/config_androiddisplay.cxx
Normal file
90
panda/src/androiddisplay/config_androiddisplay.cxx
Normal file
@ -0,0 +1,90 @@
|
||||
// Filename: config_androiddisplay.cxx
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_androiddisplay.h"
|
||||
#include "androidGraphicsPipe.h"
|
||||
#include "androidGraphicsWindow.h"
|
||||
#include "androidGraphicsStateGuardian.h"
|
||||
#include "graphicsPipeSelection.h"
|
||||
#include "dconfig.h"
|
||||
#include "pandaSystem.h"
|
||||
|
||||
#include "config_display.h"
|
||||
|
||||
Configure(config_androiddisplay);
|
||||
NotifyCategoryDef(androiddisplay, "display");
|
||||
|
||||
ConfigureFn(config_androiddisplay) {
|
||||
init_libandroiddisplay();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libandroiddisplay
|
||||
// Description: Initializes the library. This must be called at
|
||||
// least once before any of the functions or classes in
|
||||
// this library can be used. Normally it will be
|
||||
// called by the static initializers and need not be
|
||||
// called explicitly, but special cases exist.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
init_libandroiddisplay() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
init_libdisplay();
|
||||
display_cat.get_safe_ptr();
|
||||
|
||||
AndroidGraphicsPipe::init_type();
|
||||
AndroidGraphicsWindow::init_type();
|
||||
AndroidGraphicsStateGuardian::init_type();
|
||||
|
||||
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
|
||||
selection->add_pipe_type(AndroidGraphicsPipe::get_class_type(),
|
||||
AndroidGraphicsPipe::pipe_constructor);
|
||||
|
||||
PandaSystem *ps = PandaSystem::get_global_ptr();
|
||||
#ifdef OPENGLES_2
|
||||
ps->set_system_tag("OpenGL ES 2", "window_system", "Android");
|
||||
#else
|
||||
ps->set_system_tag("OpenGL ES", "window_system", "Android");
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: get_egl_error_string
|
||||
// Description: Returns the given EGL error as string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string get_egl_error_string(int error) {
|
||||
switch (error) {
|
||||
case 0x3000: return "EGL_SUCCESS"; break;
|
||||
case 0x3001: return "EGL_NOT_INITIALIZED"; break;
|
||||
case 0x3002: return "EGL_BAD_ACCESS"; break;
|
||||
case 0x3003: return "EGL_BAD_ALLOC"; break;
|
||||
case 0x3004: return "EGL_BAD_ATTRIBUTE"; break;
|
||||
case 0x3005: return "EGL_BAD_CONFIG"; break;
|
||||
case 0x3006: return "EGL_BAD_CONTEXT"; break;
|
||||
case 0x3007: return "EGL_BAD_CURRENT_SURFACE"; break;
|
||||
case 0x3008: return "EGL_BAD_DISPLAY"; break;
|
||||
case 0x3009: return "EGL_BAD_MATCH"; break;
|
||||
case 0x300A: return "EGL_BAD_NATIVE_PIXMAP"; break;
|
||||
case 0x300B: return "EGL_BAD_NATIVE_WINDOW"; break;
|
||||
case 0x300C: return "EGL_BAD_PARAMETER"; break;
|
||||
case 0x300D: return "EGL_BAD_SURFACE"; break;
|
||||
case 0x300E: return "EGL_CONTEXT_LOST"; break;
|
||||
default: return "Unknown error";
|
||||
}
|
||||
}
|
43
panda/src/androiddisplay/config_androiddisplay.h
Normal file
43
panda/src/androiddisplay/config_androiddisplay.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Filename: config_androiddisplay.h
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_ANDROIDDISPLAY_H
|
||||
#define CONFIG_ANDROIDDISPLAY_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "configVariableString.h"
|
||||
#include "configVariableBool.h"
|
||||
#include "configVariableInt.h"
|
||||
|
||||
#if defined(OPENGLES_1) && defined(OPENGLES_2)
|
||||
#error OPENGLES_1 and OPENGLES_2 cannot be defined at the same time!
|
||||
#endif
|
||||
#if !defined(OPENGLES_1) && !defined(OPENGLES_2)
|
||||
#error Either OPENGLES_1 or OPENGLES_2 must be defined when compiling androiddisplay!
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
NotifyCategoryDecl(androiddisplay, EXPCL_PANDAGLES2, EXPTP_PANDAGLES2);
|
||||
|
||||
extern EXPCL_PANDAGLES2 void init_libandroiddisplay();
|
||||
extern EXPCL_PANDAGLES2 const string get_egl_error_string(int error);
|
||||
#else
|
||||
NotifyCategoryDecl(androiddisplay, EXPCL_PANDAGLES, EXPTP_PANDAGLES);
|
||||
|
||||
extern EXPCL_PANDAGLES void init_libandroiddisplay();
|
||||
extern EXPCL_PANDAGLES const string get_egl_error_string(int error);
|
||||
#endif
|
||||
|
||||
#endif
|
6
panda/src/androiddisplay/p3androiddisplay_composite1.cxx
Normal file
6
panda/src/androiddisplay/p3androiddisplay_composite1.cxx
Normal file
@ -0,0 +1,6 @@
|
||||
#include "config_androiddisplay.cxx"
|
||||
//#include "androidGraphicsBuffer.cxx"
|
||||
#include "androidGraphicsPipe.cxx"
|
||||
//#include "androidGraphicsPixmap.cxx"
|
||||
#include "androidGraphicsStateGuardian.cxx"
|
||||
#include "androidGraphicsWindow.cxx"
|
Loading…
x
Reference in New Issue
Block a user