2013-03-02 01:09:58 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2013 The Chromium Authors
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "CCEGLView.h"
|
|
|
|
#include "CCGL.h"
|
|
|
|
#include "ccMacros.h"
|
|
|
|
#include "CCDirector.h"
|
|
|
|
#include "CCInstance.h"
|
|
|
|
#include "touch_dispatcher/CCTouch.h"
|
|
|
|
#include "touch_dispatcher/CCTouchDispatcher.h"
|
|
|
|
#include "text_input_node/CCIMEDispatcher.h"
|
|
|
|
|
|
|
|
#include "ppapi/c/ppb_opengles2.h"
|
|
|
|
#include "ppapi/cpp/graphics_3d.h"
|
|
|
|
#include "ppapi/cpp/graphics_3d_client.h"
|
|
|
|
#include "ppapi/cpp/size.h"
|
|
|
|
#include "ppapi/cpp/module.h"
|
|
|
|
#include "ppapi/cpp/completion_callback.h"
|
|
|
|
#include "ppapi/gles2/gl2ext_ppapi.h"
|
|
|
|
|
|
|
|
class OpenGLContext : public pp::Graphics3DClient
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
OpenGLContext(pp::Instance* instance, pp::Size size);
|
|
|
|
~OpenGLContext();
|
|
|
|
|
|
|
|
virtual void Graphics3DContextLost()
|
|
|
|
{
|
|
|
|
assert(!"Unexpectedly lost graphics context");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MakeContextCurrent();
|
|
|
|
void InvalidateContext();
|
|
|
|
void ResizeContext(int width, int height);
|
|
|
|
void FlushContext();
|
2013-06-15 14:03:30 +08:00
|
|
|
pp::Size GetSize() { return _size; }
|
2013-03-02 01:09:58 +08:00
|
|
|
private:
|
2013-06-15 14:03:30 +08:00
|
|
|
pp::Size _size;
|
|
|
|
pp::Graphics3D _graphics3d;
|
|
|
|
const struct PPB_OpenGLES2* _gles2_interface;
|
|
|
|
pp::Instance* _instance;
|
2013-03-02 01:09:58 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
OpenGLContext::OpenGLContext(pp::Instance* instance, pp::Size size) :
|
2013-06-15 14:03:30 +08:00
|
|
|
pp::Graphics3DClient(instance), _size(size), _instance(instance)
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
pp::Module* module = pp::Module::Get();
|
|
|
|
assert(module);
|
2013-06-15 14:03:30 +08:00
|
|
|
_gles2_interface = static_cast<const struct PPB_OpenGLES2*>(
|
2013-03-02 01:09:58 +08:00
|
|
|
module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE));
|
2013-06-15 14:03:30 +08:00
|
|
|
assert(_gles2_interface);
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
OpenGLContext::~OpenGLContext()
|
|
|
|
{
|
|
|
|
CCLOG("OpenGLContext::~OpenGLContext");
|
|
|
|
glSetCurrentContextPPAPI(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLContext::MakeContextCurrent()
|
|
|
|
{
|
|
|
|
CCLOG("OpenGLContext::MakeContextCurrent %dx%d",
|
2013-06-15 14:03:30 +08:00
|
|
|
_size.width(), _size.height());
|
2013-03-02 01:09:58 +08:00
|
|
|
|
|
|
|
// Lazily create the Pepper context.
|
2013-06-15 14:03:30 +08:00
|
|
|
if (_graphics3d.is_null())
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
int32_t attribs[] = {
|
|
|
|
PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
|
|
|
|
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
|
|
|
|
PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
|
|
|
|
PP_GRAPHICS3DATTRIB_SAMPLES, 0,
|
|
|
|
PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
|
2013-06-15 14:03:30 +08:00
|
|
|
PP_GRAPHICS3DATTRIB_WIDTH, _size.width(),
|
|
|
|
PP_GRAPHICS3DATTRIB_HEIGHT, _size.height(),
|
2013-03-02 01:09:58 +08:00
|
|
|
PP_GRAPHICS3DATTRIB_NONE
|
|
|
|
};
|
2013-06-15 14:03:30 +08:00
|
|
|
_graphics3d = pp::Graphics3D(_instance, pp::Graphics3D(), attribs);
|
|
|
|
if (_graphics3d.is_null())
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
glSetCurrentContextPPAPI(0);
|
|
|
|
return false;
|
|
|
|
}
|
2013-06-15 14:03:30 +08:00
|
|
|
bool rtn = _instance->BindGraphics(_graphics3d);
|
2013-03-02 01:09:58 +08:00
|
|
|
assert(rtn && "BindGraphics failed");
|
|
|
|
if (!rtn)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
CCLOG("glSetCurrentContextPPAPI: %p", (void*)_graphics3d.pp_resource());
|
|
|
|
glSetCurrentContextPPAPI(_graphics3d.pp_resource());
|
2013-03-02 01:09:58 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLContext::InvalidateContext()
|
|
|
|
{
|
|
|
|
CCLOG("InvalidateContext");
|
|
|
|
glSetCurrentContextPPAPI(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLContext::ResizeContext(int width, int height)
|
|
|
|
{
|
|
|
|
CCLOG("OpenGLContext::ResizeContext %dx%d", width, height);
|
2013-06-15 14:03:30 +08:00
|
|
|
_size.SetSize(width, height);
|
|
|
|
if (!_graphics3d.is_null())
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
_graphics3d.ResizeBuffers(width, height);
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLContext::FlushContext()
|
|
|
|
{
|
|
|
|
//CCLOG("OpenGLContext::FlushContext");
|
2013-06-15 14:03:30 +08:00
|
|
|
_graphics3d.SwapBuffers(pp::BlockUntilComplete());
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
EGLView::EGLView() : bIsInit(false), bIsMouseDown(false), _frameZoomFactor(1.0f), _context(NULL)
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
CCLOG("CCEGLView::EGLView");
|
2013-06-15 14:03:30 +08:00
|
|
|
pthread_mutex_init(&_mutex, NULL);
|
2013-03-02 01:09:58 +08:00
|
|
|
initGL();
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
EGLView::~EGLView()
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::setFrameSize(float width, float height)
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
EGLViewProtocol::setFrameSize(width, height);
|
2013-06-15 14:03:30 +08:00
|
|
|
if (_context)
|
|
|
|
_context->ResizeContext(width, height);
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::setViewPortInPoints(float x , float y , float w , float h)
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
glViewport((GLint)(x * _scaleX * _frameZoomFactor+ _viewPortRect.origin.x * _frameZoomFactor),
|
|
|
|
(GLint)(y * _scaleY * _frameZoomFactor + _viewPortRect.origin.y * _frameZoomFactor),
|
|
|
|
(GLsizei)(w * _scaleX * _frameZoomFactor),
|
|
|
|
(GLsizei)(h * _scaleY * _frameZoomFactor));
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::setScissorInPoints(float x , float y , float w , float h)
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
glScissor((GLint)(x * _scaleX * _frameZoomFactor + _viewPortRect.origin.x * _frameZoomFactor),
|
|
|
|
(GLint)(y * _scaleY * _frameZoomFactor + _viewPortRect.origin.y * _frameZoomFactor),
|
|
|
|
(GLsizei)(w * _scaleX * _frameZoomFactor),
|
|
|
|
(GLsizei)(h * _scaleY * _frameZoomFactor));
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
bool EGLView::isOpenGLReady()
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
return bIsInit;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::end()
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
delete this;
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::swapBuffers()
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
if (!bIsInit)
|
|
|
|
return;
|
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
_context->FlushContext();
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::setIMEKeyboardState(bool bOpen)
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
bool EGLView::initGL()
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
CCLOG("initGL: instance=%p", g_instance);
|
|
|
|
assert(g_instance);
|
2013-06-15 14:03:30 +08:00
|
|
|
assert(!_context);
|
2013-03-02 01:09:58 +08:00
|
|
|
const pp::Size& size = g_instance->Size();
|
|
|
|
setFrameSize(size.width(), size.height());
|
2013-06-15 14:03:30 +08:00
|
|
|
_context = new OpenGLContext(g_instance, size);
|
|
|
|
CCLOG("initGL: _context=%p", _context);
|
|
|
|
bool rtn = _context->MakeContextCurrent();
|
2013-03-02 01:09:58 +08:00
|
|
|
CCLOG("MakeContextCurrent returned: %d", rtn);
|
|
|
|
assert(rtn == true && "MakeContextCurrent failed");
|
|
|
|
if (!rtn)
|
|
|
|
return false;
|
|
|
|
bIsInit = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::destroyGL()
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
delete _context;
|
2013-03-02 01:09:58 +08:00
|
|
|
bIsInit = false;
|
|
|
|
CCLOG("destroyGL");
|
|
|
|
}
|
|
|
|
|
2013-07-12 13:11:21 +08:00
|
|
|
EGLView* EGLView::getInstance()
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
static EGLView* s_pEglView = NULL;
|
2013-03-02 01:09:58 +08:00
|
|
|
if (s_pEglView == NULL)
|
|
|
|
{
|
2013-06-20 14:13:12 +08:00
|
|
|
CCLOG("creating EGLView");
|
|
|
|
s_pEglView = new EGLView();
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
return s_pEglView;
|
|
|
|
}
|
|
|
|
|
2013-07-12 13:11:21 +08:00
|
|
|
// XXX: deprecated
|
|
|
|
EGLView* EGLView::sharedOpenGLView()
|
|
|
|
{
|
|
|
|
return EGLView::getInstance();
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::HandleMouseEvent(const pp::MouseInputEvent* event)
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
pp::Point pos = event->GetPosition();
|
|
|
|
float x = pos.x();
|
|
|
|
float y = pos.y();
|
|
|
|
int touchID = 1;
|
|
|
|
|
|
|
|
// Clamp event position to be within cocos2dx window size
|
2013-06-20 14:13:12 +08:00
|
|
|
Size frame_size = getFrameSize();
|
2013-03-02 01:09:58 +08:00
|
|
|
float max_y = frame_size.height;
|
|
|
|
float max_x = frame_size.width;
|
|
|
|
|
|
|
|
if (x < 0)
|
|
|
|
x = 0;
|
|
|
|
if (y < 0)
|
|
|
|
y = 0;
|
|
|
|
if (y > max_y)
|
|
|
|
y = max_y;
|
|
|
|
if (x > max_x)
|
|
|
|
x = max_x;
|
|
|
|
|
|
|
|
switch (event->GetType())
|
|
|
|
{
|
|
|
|
case PP_INPUTEVENT_TYPE_MOUSEDOWN:
|
|
|
|
handleTouchesBegin(1, &touchID, &x, &y);
|
|
|
|
bIsMouseDown = true;
|
|
|
|
break;
|
|
|
|
case PP_INPUTEVENT_TYPE_MOUSEUP:
|
|
|
|
handleTouchesEnd(1, &touchID, &x, &y);
|
|
|
|
bIsMouseDown = false;
|
|
|
|
break;
|
|
|
|
case PP_INPUTEVENT_TYPE_MOUSEMOVE:
|
|
|
|
if (bIsMouseDown)
|
|
|
|
handleTouchesMove(1, &touchID, &x, &y);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::ProcessEventQueue()
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
const pp::Size& size = g_instance->Size();
|
|
|
|
// If the size of the global instance has changed then
|
|
|
|
// we need to update our GL frame size accordingly
|
2013-06-15 14:03:30 +08:00
|
|
|
if (size != _context->GetSize())
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
|
|
|
setFrameSize(size.width(), size.height());
|
|
|
|
}
|
|
|
|
|
2013-06-15 14:03:30 +08:00
|
|
|
pthread_mutex_lock(&_mutex);
|
|
|
|
while (_event_queue.size())
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
pp::InputEvent event = _event_queue.front();
|
|
|
|
_event_queue.pop();
|
2013-03-02 01:09:58 +08:00
|
|
|
PP_InputEvent_Type type = event.GetType();
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case PP_INPUTEVENT_TYPE_KEYDOWN:
|
|
|
|
CCLOG("got KEYDOWN");
|
|
|
|
break;
|
|
|
|
case PP_INPUTEVENT_TYPE_KEYUP:
|
|
|
|
CCLOG("got KEYUP");
|
|
|
|
break;
|
|
|
|
case PP_INPUTEVENT_TYPE_CHAR:
|
|
|
|
CCLOG("got KEYCHAR");
|
|
|
|
break;
|
|
|
|
case PP_INPUTEVENT_TYPE_MOUSEENTER:
|
|
|
|
CCLOG("got MOUSEENTER");
|
|
|
|
break;
|
|
|
|
case PP_INPUTEVENT_TYPE_MOUSELEAVE:
|
|
|
|
CCLOG("got MOUSELEAVE");
|
|
|
|
break;
|
|
|
|
case PP_INPUTEVENT_TYPE_MOUSEDOWN:
|
|
|
|
case PP_INPUTEVENT_TYPE_MOUSEUP:
|
|
|
|
case PP_INPUTEVENT_TYPE_MOUSEMOVE:
|
|
|
|
{
|
|
|
|
const pp::MouseInputEvent* mevent =
|
|
|
|
reinterpret_cast<const pp::MouseInputEvent*>(&event);
|
|
|
|
HandleMouseEvent(mevent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
CCLOG("unhandled event type: %d", type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-06-15 14:03:30 +08:00
|
|
|
pthread_mutex_unlock(&_mutex);
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
void EGLView::AddEvent(const pp::InputEvent& event)
|
2013-03-02 01:09:58 +08:00
|
|
|
{
|
2013-06-15 14:03:30 +08:00
|
|
|
pthread_mutex_lock(&_mutex);
|
|
|
|
_event_queue.push(event);
|
|
|
|
pthread_mutex_unlock(&_mutex);
|
2013-03-02 01:09:58 +08:00
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
CocosPepperInstance* EGLView::g_instance;
|
2013-03-02 01:09:58 +08:00
|
|
|
|
|
|
|
NS_CC_END
|