2 * Copyright (C) 2011 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "anbox/graphics/emugl/WindowSurface.h"
18 #include "anbox/graphics/emugl/RendererConfig.h"
19 #include "anbox/logger.h"
21 #include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
23 #include <GLES/glext.h>
29 WindowSurface::WindowSurface(EGLDisplay display, EGLConfig config)
31 mAttachedColorBuffer(NULL),
39 WindowSurface::~WindowSurface() {
41 s_egl.eglDestroySurface(mDisplay, mSurface);
45 WindowSurface *WindowSurface::create(EGLDisplay display, EGLConfig config,
46 int p_width, int p_height) {
47 // allocate space for the WindowSurface object
48 WindowSurface *win = new WindowSurface(display, config);
53 // Create a pbuffer to be used as the egl surface
55 if (!win->resize(p_width, p_height)) {
63 void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer) {
64 mAttachedColorBuffer = p_colorBuffer;
66 // resize the window if the attached color buffer is of different
68 unsigned int cbWidth = mAttachedColorBuffer->getWidth();
69 unsigned int cbHeight = mAttachedColorBuffer->getHeight();
71 if (cbWidth != mWidth || cbHeight != mHeight) {
72 resize(cbWidth, cbHeight);
76 void WindowSurface::bind(RenderContextPtr p_ctx, BindType p_bindType) {
77 if (p_bindType == BIND_READ) {
79 } else if (p_bindType == BIND_DRAW) {
81 } else if (p_bindType == BIND_READDRAW) {
87 bool WindowSurface::flushColorBuffer() {
88 if (!mAttachedColorBuffer) {
91 if (!mWidth || !mHeight) {
95 if (mAttachedColorBuffer->getWidth() != mWidth ||
96 mAttachedColorBuffer->getHeight() != mHeight) {
97 // XXX: should never happen - how this needs to be handled?
98 ERROR("Dimensions do not match");
103 ERROR("Draw context is NULL");
107 // Make the surface current
108 EGLContext prevContext = s_egl.eglGetCurrentContext();
109 EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
110 EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
112 if (!s_egl.eglMakeCurrent(mDisplay, mSurface, mSurface,
113 mDrawContext->getEGLContext())) {
114 ERROR("Failed to make draw context current");
118 mAttachedColorBuffer->blitFromCurrentReadBuffer();
120 // restore current context/surface
121 s_egl.eglMakeCurrent(mDisplay, prevDrawSurf, prevReadSurf, prevContext);
126 bool WindowSurface::resize(unsigned int p_width, unsigned int p_height) {
127 if (mSurface && mWidth == p_width && mHeight == p_height) {
132 EGLContext prevContext = s_egl.eglGetCurrentContext();
133 EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
134 EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
135 EGLSurface prevPbuf = mSurface;
136 bool needRebindContext =
137 mSurface && (prevReadSurf == mSurface || prevDrawSurf == mSurface);
139 if (needRebindContext) {
140 s_egl.eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
145 s_egl.eglDestroySurface(mDisplay, mSurface);
149 const EGLint pbufAttribs[5] = {
150 EGL_WIDTH, static_cast<EGLint>(p_width),
151 EGL_HEIGHT, static_cast<EGLint>(p_height),
155 mSurface = s_egl.eglCreatePbufferSurface(mDisplay, mConfig, pbufAttribs);
156 if (mSurface == EGL_NO_SURFACE) {
157 ERROR("Failed to create/resize pbuffer");
164 if (needRebindContext) {
165 s_egl.eglMakeCurrent(
166 mDisplay, (prevDrawSurf == prevPbuf) ? mSurface : prevDrawSurf,
167 (prevReadSurf == prevPbuf) ? mSurface : prevReadSurf, prevContext);