fd60aba7e1f16250b32a44d0eeb39d746a961456
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / graphics / emugl / WindowSurface.cpp
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 #include "anbox/graphics/emugl/WindowSurface.h"
18 #include "anbox/graphics/emugl/RendererConfig.h"
19 #include "anbox/logger.h"
20
21 #include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
22
23 #include <GLES/glext.h>
24
25 #include <stdio.h>
26 #include <string.h>
27
28
29 WindowSurface::WindowSurface(EGLDisplay display, EGLConfig config)
30     : mSurface(NULL),
31       mAttachedColorBuffer(NULL),
32       mReadContext(NULL),
33       mDrawContext(NULL),
34       mWidth(0),
35       mHeight(0),
36       mConfig(config),
37       mDisplay(display) {}
38
39 WindowSurface::~WindowSurface() {
40   if (mSurface) {
41     s_egl.eglDestroySurface(mDisplay, mSurface);
42   }
43 }
44
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);
49   if (!win) {
50     return NULL;
51   }
52
53   // Create a pbuffer to be used as the egl surface
54   // for that window.
55   if (!win->resize(p_width, p_height)) {
56     delete win;
57     return NULL;
58   }
59
60   return win;
61 }
62
63 void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer) {
64   mAttachedColorBuffer = p_colorBuffer;
65
66   // resize the window if the attached color buffer is of different
67   // size.
68   unsigned int cbWidth = mAttachedColorBuffer->getWidth();
69   unsigned int cbHeight = mAttachedColorBuffer->getHeight();
70
71   if (cbWidth != mWidth || cbHeight != mHeight) {
72     resize(cbWidth, cbHeight);
73   }
74 }
75
76 void WindowSurface::bind(RenderContextPtr p_ctx, BindType p_bindType) {
77   if (p_bindType == BIND_READ) {
78     mReadContext = p_ctx;
79   } else if (p_bindType == BIND_DRAW) {
80     mDrawContext = p_ctx;
81   } else if (p_bindType == BIND_READDRAW) {
82     mReadContext = p_ctx;
83     mDrawContext = p_ctx;
84   }
85 }
86
87 bool WindowSurface::flushColorBuffer() {
88   if (!mAttachedColorBuffer) {
89     return true;
90   }
91   if (!mWidth || !mHeight) {
92     return false;
93   }
94
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");
99     return false;
100   }
101
102   if (!mDrawContext) {
103     ERROR("Draw context is NULL");
104     return false;
105   }
106
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);
111
112   if (!s_egl.eglMakeCurrent(mDisplay, mSurface, mSurface,
113                             mDrawContext->getEGLContext())) {
114     ERROR("Failed to make draw context current");
115     return false;
116   }
117
118   mAttachedColorBuffer->blitFromCurrentReadBuffer();
119
120   // restore current context/surface
121   s_egl.eglMakeCurrent(mDisplay, prevDrawSurf, prevReadSurf, prevContext);
122
123   return true;
124 }
125
126 bool WindowSurface::resize(unsigned int p_width, unsigned int p_height) {
127   if (mSurface && mWidth == p_width && mHeight == p_height) {
128     // no need to resize
129     return true;
130   }
131
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);
138
139   if (needRebindContext) {
140     s_egl.eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
141                          EGL_NO_CONTEXT);
142   }
143
144   if (mSurface) {
145     s_egl.eglDestroySurface(mDisplay, mSurface);
146     mSurface = NULL;
147   }
148
149   const EGLint pbufAttribs[5] = {
150       EGL_WIDTH, static_cast<EGLint>(p_width),
151       EGL_HEIGHT, static_cast<EGLint>(p_height),
152       EGL_NONE,
153   };
154
155   mSurface = s_egl.eglCreatePbufferSurface(mDisplay, mConfig, pbufAttribs);
156   if (mSurface == EGL_NO_SURFACE) {
157     ERROR("Failed to create/resize pbuffer");
158     return false;
159   }
160
161   mWidth = p_width;
162   mHeight = p_height;
163
164   if (needRebindContext) {
165     s_egl.eglMakeCurrent(
166         mDisplay, (prevDrawSurf == prevPbuf) ? mSurface : prevDrawSurf,
167         (prevReadSurf == prevPbuf) ? mSurface : prevReadSurf, prevContext);
168   }
169
170   return true;
171 }