blob: 444eff617d5dc0f84dcda5efa75fa6870b640fee [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "EglContext.h"
#include "EglDisplay.h"
#include "EglGlobalInfo.h"
#include "EglOsApi.h"
#include "EglPbufferSurface.h"
#include "ThreadInfo.h"
unsigned int EglContext::s_nextContextHndl = 0;
extern EglGlobalInfo* g_eglInfo; // defined in EglImp.cpp
bool EglContext::usingSurface(SurfacePtr surface) {
return surface.get() == m_read.get() || surface.get() == m_draw.get();
}
EglContext::EglContext(EglDisplay *dpy,
EglOS::Context* context,
ContextPtr shared_context,
EglConfig* config,
GLEScontext* glesCtx,
GLESVersion ver,
ObjectNameManager* mngr) :
m_dpy(dpy),
m_native(context),
m_config(config),
m_glesContext(glesCtx),
m_version(ver),
m_mngr(mngr) {
m_shareGroup = shared_context.get()?
mngr->attachShareGroup(context,shared_context->nativeType()):
mngr->createShareGroup(context);
m_hndl = ++s_nextContextHndl;
}
EglContext::~EglContext()
{
ThreadInfo* thread = getThreadInfo();
// get the current context
ContextPtr currentCtx = thread->eglContext;
if (currentCtx && !m_dpy->getContext((EGLContext)SafePointerFromUInt(
currentCtx->getHndl()))) {
currentCtx.reset();
}
SurfacePtr currentRead = currentCtx ? currentCtx->read() : nullptr;
SurfacePtr currentDraw = currentCtx ? currentCtx->draw() : nullptr;
// we need to make the context current before releasing GL resources.
// create a dummy surface first
std::shared_ptr<EglPbufferSurface> pbSurface(new EglPbufferSurface(m_dpy,
m_config));
pbSurface->setAttrib(EGL_WIDTH, 1);
pbSurface->setAttrib(EGL_HEIGHT, 1);
EglOS::PbufferInfo pbInfo;
pbSurface->getDim(&pbInfo.width, &pbInfo.height, &pbInfo.largest);
pbSurface->getTexInfo(&pbInfo.target, &pbInfo.format);
pbInfo.hasMipmap = false;
EglOS::Surface* pb = m_dpy->nativeType()->createPbufferSurface(
m_config->nativeFormat(), &pbInfo);
assert(pb);
if (pb) {
const bool res = m_dpy->nativeType()->makeCurrent(pb, pb, m_native);
assert(res);
(void)res;
pbSurface->setNativePbuffer(pb);
}
//
// release GL resources. m_shareGroup, m_mngr and m_glesContext hold
// smart pointers to share groups. We must clean them up when the context
// is current.
//
m_shareGroup.reset();
if (m_mngr) {
m_mngr->deleteShareGroup(m_native);
}
//
// call the client-api to remove the GLES context
//
g_eglInfo->getIface(version())->deleteGLESContext(m_glesContext);
//
// restore the current context
//
if (currentCtx) {
m_dpy->nativeType()->makeCurrent(currentRead->native(),
currentDraw->native(),
currentCtx->nativeType());
} else {
m_dpy->nativeType()->makeCurrent(nullptr, nullptr, nullptr);
}
//
// remove the context in the underlying OS layer
//
m_dpy->nativeType()->destroyContext(m_native);
}
void EglContext::setSurfaces(SurfacePtr read,SurfacePtr draw)
{
m_read = read;
m_draw = draw;
}
bool EglContext::getAttrib(EGLint attrib,EGLint* value) {
switch(attrib) {
case EGL_CONFIG_ID:
*value = m_config->id();
break;
default:
return false;
}
return true;
}