⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glcanvasmodule.cpp

📁 python s60 1.4.5版本的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**
 * ====================================================================
 * glcanvasmodule.cpp
 *
 * Copyright (c) 2006 - 2007 Nokia Corporation
 *
 * 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 "glcanvas.h"

/* EGL 1.1 enumeration */
#ifndef EGL_VERSION_1_1
#define EGL_CONTEXT_LOST	       0x300E
#define EGL_BIND_TO_TEXTURE_RGB        0x3039
#define EGL_BIND_TO_TEXTURE_RGBA       0x303A
#define EGL_MIN_SWAP_INTERVAL	       0x303B
#define EGL_MAX_SWAP_INTERVAL	       0x303C
#define EGL_BACK_BUFFER		       0x3084
#endif

/**
 * Implementation of GLCanvas
 *
 * A big part of the implementation has been copied from
 * the original Canvas object implementation in
 * appui/appuifw/appuifwmodule.cpp
 *
 */

CGLCanvas::CGLCanvas(PyObject *aDrawCallback, PyObject *aEventCallback, PyObject *aResizeCallback) {
    iDrawCallback  = aDrawCallback;
    iEventCallback = aEventCallback;
    iResizeCallback = aResizeCallback;
    iOpenGLInitialized = 0;
}

void CGLCanvas::ConstructL(const TRect& aRect, const CCoeControl* aParent) {
  CreateWindowL(aParent);
  SetRect(aRect);
  ActivateL();
#ifdef DEBUG_GLCANVAS
  DEBUGMSG2("aRect Size: %d x %d", aRect.Size().iWidth, aRect.Size().iHeight);
  DEBUGMSG2("aRect PosX: %d PosY: %d", aRect.iTl.iX, aRect.iTl.iY);
#endif
}

CGLCanvas::~CGLCanvas() {
#ifdef DEBUG_GLCANVAS
  DEBUGMSG("CGLCanvas destructor");
#endif
  eglMakeCurrent( iEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
  eglDestroySurface( iEglDisplay, iEglSurface );
  eglDestroyContext( iEglDisplay, iEglContext );
  // Release resources associated
  // with EGL and OpenGL ES
  eglTerminate( iEglDisplay );
}

TKeyResponse CGLCanvas::OfferKeyEventL(const TKeyEvent& aKeyEvent, 
				      TEventCode aType) {
  PyObject *arg=NULL, *ret=NULL;
  CCoeControl::OfferKeyEventL(aKeyEvent,aType);
  if (!iEventCallback) 
    return EKeyWasNotConsumed;
  PyEval_RestoreThread(PYTHON_TLS->thread_state);
  arg=Py_BuildValue("({s:i,s:i,s:i,s:i})",
        "type",aType,
        "keycode",aKeyEvent.iCode,
        "scancode", aKeyEvent.iScanCode, 
        "modifiers", aKeyEvent.iModifiers);
  if (!arg) 
    goto error;
  ret=PyEval_CallObject(iEventCallback,arg);
  Py_DECREF(arg);
  if (!ret) 
    goto error;
  Py_DECREF(ret);
  PyEval_SaveThread();
  return EKeyWasNotConsumed;
error:
  PyErr_Print();
  PyEval_SaveThread();
  return EKeyWasNotConsumed;
}

/**
 * Creates a new EGL rendering context on screen. Sets a Python exception if
 * the operation fails.
 *
 * @param attrib_list An array of desired attributes.
 * @return 1 on success, 0 on failure.
 */
int CGLCanvas::CreateContext(EGLint *attrib_list) {
#ifdef DEBUG_GLCANVAS
  DEBUGMSG("CGLCanvas::CreateContext\n");
#endif
  assert(attrib_list != NULL);
  
  // Initialize frame counter
  iFrame = 0;
  
  // Describes the format, type and 
  // size of the color buffers and
  // ancillary buffers for EGLSurface
  EGLConfig Config;                        
  
  // Get the display for drawing graphics
  iEglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
  if ( iEglDisplay == NULL )
      {
      PyErr_Format(PyExc_RuntimeError, "eglGetDisplay failed [Errno %d]", eglGetError());
      return NULL;
      }

  // Initialize display 
  if ( eglInitialize( iEglDisplay, NULL, NULL ) == EGL_FALSE )
      {
      PyErr_Format(PyExc_RuntimeError, "eglInitialize [Errno %d, disp: %x]", eglGetError(), iEglDisplay);
      return NULL;
      }
  
  // Pointer for EGLConfigs
  EGLConfig *configList = NULL;
  EGLint numOfConfigs = 0;
  EGLint configSize   = 0;
  // Get the number of possible EGLConfigs
  if ( eglGetConfigs( iEglDisplay, configList, configSize, &numOfConfigs ) 
      == EGL_FALSE )
      {
      PyErr_Format(PyExc_ValueError, "eglGetConfigs failed [Errno %d]", eglGetError());
      return NULL;
      }
  configSize = numOfConfigs;
  
  // Allocate memory for the configList
  configList = (EGLConfig*) glcanvas_alloc( sizeof(EGLConfig)*configSize );
  if ( configList == NULL )
      {
      PyErr_SetString(PyExc_ValueError, "Config alloc failed");
      return NULL;
      }

  /* Define properties for the wanted EGLSurface.
     To get the best possible performance, choose
     an EGLConfig with a buffersize matching
     the current window's display mode*/
  
  // Choose an EGLConfig that best matches to the properties in attrib_list 
  if ( eglChooseConfig( iEglDisplay, attrib_list, configList, configSize, 
                       &numOfConfigs ) == EGL_FALSE )
      {
      glcanvas_free(configList);
      PyErr_Format(PyExc_TypeError, "No matching configuration found. [Errno %d]", eglGetError());
      return NULL;
      }
  
  // Choose the best EGLConfig. EGLConfigs 
  // returned by eglChooseConfig are sorted so 
  // that the best matching EGLConfig is first in
  // the list.
  Config = configList[0];
  
  // Free configList, not used anymore.
  glcanvas_free( configList );
  
  // Create a window where the graphics are blitted 
  iEglSurface = eglCreateWindowSurface( iEglDisplay, Config, &Window(), NULL );
  if ( iEglSurface == NULL )
      {
      PyErr_Format(PyExc_RuntimeError, "eglCreateWindowSurface failed [Errno %d]", eglGetError());
      return NULL;
      }
  
  // Create a rendering context 
  iEglContext = eglCreateContext( iEglDisplay, Config, EGL_NO_CONTEXT, NULL );
  if ( iEglContext == NULL )
      {
      PyErr_Format(PyExc_RuntimeError, "eglCreateContext failed [Errno %d]", eglGetError());
      return NULL;
      }
  /* Make the context current. Binds context to the current rendering thread
     and surface.*/
  if ( eglMakeCurrent( iEglDisplay, iEglSurface, iEglSurface, iEglContext ) 
      == EGL_FALSE )
      {
      PyErr_Format(PyExc_RuntimeError, "eglMakeCurrent failed [Errno %d]", eglGetError());
      return NULL;
      }
  iOpenGLInitialized = 1;
  return 1;
}

void CGLCanvas::makeCurrent() {
  /* Make the context current. Binds context to the current rendering thread
  and surface.*/
  if ( eglMakeCurrent( iEglDisplay, iEglSurface, iEglSurface, iEglContext ) 
      == EGL_FALSE )
      {
      PyErr_SetString(PyExc_RuntimeError, "eglMakeCurrent failed");
      return;
      }
  return;
}

PyObject *CGLCanvas::GetRedrawCallBack() {
  return iDrawCallback;
}

PyObject *CGLCanvas::GetEventCallBack() {
  return iEventCallback;
}

PyObject *CGLCanvas::GetResizeCallBack() {
  return iResizeCallback;
}

void CGLCanvas::SetRedrawCallBack(PyObject *cb) {
  if(PyCallable_Check(cb) ) {
    Py_XINCREF(cb);
  } else if(cb == Py_None) {
    cb = NULL;
  } else {
    PyErr_SetString(PyExc_TypeError, "Callable of None expected");
    return;
  }
  
  if(iDrawCallback) {
    Py_XDECREF(iDrawCallback);
  }
  iDrawCallback = cb;
  return;
}

void CGLCanvas::SetEventCallBack(PyObject *cb) {
  if(PyCallable_Check(cb) ) {
    Py_XINCREF(cb);
  } else if(cb == Py_None) {
    cb = NULL;
  } else {
    PyErr_SetString(PyExc_TypeError, "Callable of None expected");
    return;
  }
  
  if(iEventCallback) {
    Py_XDECREF(iEventCallback);
  }
  iEventCallback = cb;
  return;
}

void CGLCanvas::SetResizeCallBack(PyObject *cb) {
  if(PyCallable_Check(cb) ) {
    Py_XINCREF(cb);
  } else if(cb == Py_None) {
    cb = NULL;
  } else {
    PyErr_SetString(PyExc_TypeError, "Callable of None expected");
    return;
  }
  
  if(iResizeCallback) {
    Py_XDECREF(iResizeCallback);
  }
  iResizeCallback = cb;
  return;
}

/**
 * Returns the buffer size for current display mode
 *
 * @return Buffer size in bits
 */
int CGLCanvas::GetBufferSize() {
  TDisplayMode DMode = Window().DisplayMode();
  int BufferSize = 0;
#ifdef DEBUG_GLCANVAS
  DEBUGMSG1("DMode = %x", DMode);
#endif
  switch ( DMode ) {
    case(EColor4K):
      BufferSize = 12;
      break;
    case(EColor64K):
      BufferSize = 16;
      break;
    case(EColor16M):
      BufferSize = 24;
      break;
    #if SERIES60_VERSION >= 28
    case(EColor16MA):
      BufferSize = 32;
      break; 
    #endif
    case(EColor16MU):
      BufferSize = 32;
      break;
    default:
      return -1;
  }
  return BufferSize;
}
/* FIXME This method is declared const so it should not alter the
   state of the object, but arbitrary code execution is allowed in the
   Python callback. This could lead to trouble if the GLCanvas is
   altered there. Maybe we should switch to double buffering completely or 
   invoke the callback via a callgate? */
void CGLCanvas::Draw(const TRect& /*aRect*/) const {     
#ifdef DEBUG_GLCANVAS
  DEBUGMSG("GLCanvas::Draw");
  DEBUGMSG1("Frame: %d", iFrame);
#endif

// This fails on the emulator
#ifndef __WINS__
  redraw();
#endif


}

void CGLCanvas::redraw() const {
  if( !iOpenGLInitialized ) {
    return;
  }
  
  if (iDrawCallback) {
    int in_interpreter=(_PyThreadState_Current == PYTHON_TLS->thread_state);
    if (!in_interpreter)
      PyEval_RestoreThread(PYTHON_TLS->thread_state);
    PyObject *frame = Py_BuildValue("(i)", iFrame);
    app_callback_handler(iDrawCallback,frame);
    if (!in_interpreter)
      PyEval_SaveThread();
  }
  
  eglSwapBuffers( this->iEglDisplay, this->iEglSurface );
    // This keeps the backlight turned on when the rendering is continuous
  if ( !(iFrame%50) ) {
    User::ResetInactivityTime();
    User::After(0);
#ifdef DEBUG_GLCANVAS
    DEBUGMSG("User::ResetinactivityTime()");
    DEBUGMSG("User::After(0)");
#endif
  }
}

void CGLCanvas::SizeChanged() { 
#ifdef DEBUG_GLCANVAS
  DEBUGMSG("GLCanvas::SizeChanged()\n");
  TSize size = Size();
  TPoint position = Position();
  DEBUGMSG2("New size: %d x %d", size.iWidth, size.iHeight);
  DEBUGMSG2("New posX: %d posY: %d", position.iX, position.iY);
#endif
  if( !iOpenGLInitialized ) {
    return;
  }
  if (iResizeCallback) {
    int in_interpreter=(_PyThreadState_Current == PYTHON_TLS->thread_state);
    if (!in_interpreter)
      PyEval_RestoreThread(PYTHON_TLS->thread_state);
    app_callback_handler(iResizeCallback,NULL);
    if (!in_interpreter)
      PyEval_SaveThread();
  }
}

#define ADD_EGL_ATTRIB_VALUE(ptr,param,value) do { *ptr=param; ptr++; *ptr=value; ptr++; } while(0)
#define TERMINATE_EGL_ATTRIB_LIST(ptr) do { *ptr=EGL_NONE; } while(0)

EGLint *CGLCanvas::GenerateEglAttributes(PyObject *options) {
  PyObject *optlist = NULL;
  int optsize = 0;
  EGLint *attrib_list = NULL;
  EGLint *attrib_list_item = NULL;
  int i = 0;
#ifdef DEBUG_GLCANVAS
  DEBUGMSG("GLCanvas_egl_attrs()\n");
#endif
  
  if(!PyDict_Check(options) ) {
    PyErr_SetString(PyExc_TypeError, "Expecting a dict");
    return NULL;
  }
  
  // See if the user wants to specify a custom buffer size
  if(PyDict_GetItem(options, PyInt_FromLong(EGL_BUFFER_SIZE)) == NULL ) {
    PyDict_SetItem(options,Py_BuildValue("i", EGL_BUFFER_SIZE), Py_BuildValue("i", GetBufferSize()) );
  }
  
  // See if the user wants to specify a custom buffer size
  if(PyDict_GetItem(options, PyInt_FromLong(EGL_DEPTH_SIZE)) == NULL ) {
    PyDict_SetItem(options, Py_BuildValue("i", EGL_DEPTH_SIZE), Py_BuildValue("i", GLCANVAS_DEFAULT_DEPTH_SIZE));
  }
  
  // Build an array from the dictionary items
  optlist = PyDict_Items(options);
  optsize = PyList_Size(optlist);
  
  attrib_list = (EGLint*)glcanvas_alloc( (sizeof(EGLint) * ((optsize)*2)) + 1 );
  if(attrib_list == NULL) {
    return (EGLint*)PyErr_NoMemory();
  }
  
  // Take a copy of the array pointer, we'll be incrementing this while adding new values.
  attrib_list_item = attrib_list;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -