1 /*
2 * Copyright (C) 2018 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 #undef NDEBUG
17
18 #include "Context.h"
19 #include "EglConfig.h"
20 #include "EglContext.h"
21 #include "EglImage.h"
22 #include "EglSurface.h"
23 #include "EglSync.h"
24
25 #include <cassert>
26 #include <cerrno>
27 #include <cstring>
28 #include <string>
29
30 #include <unistd.h>
31
32 #include <GLES/gl.h>
33 #include <GLES/glext.h>
34
35 #include <OpenGLESDispatch/EGLDispatch.h>
36 #include <OpenGLESDispatch/GLESv1Dispatch.h>
37 #include <OpenGLESDispatch/GLESv3Dispatch.h>
38
39 #include "virgl_hw.h"
40
41 #include "RenderControl.h"
42
43 #include <hardware/gralloc.h>
44 #include <hardware/gralloc1.h>
45 #include <nativebase/nativebase.h>
46 #include <system/window.h>
47
incRefANWB(android_native_base_t * base)48 static void incRefANWB(android_native_base_t* base) {
49 ANativeWindowBuffer* anwb = reinterpret_cast<ANativeWindowBuffer*>(base);
50 anwb->layerCount++;
51 }
52
decRefANWB(android_native_base_t * base)53 static void decRefANWB(android_native_base_t* base) {
54 ANativeWindowBuffer* anwb = reinterpret_cast<ANativeWindowBuffer*>(base);
55 if (anwb->layerCount > 0) {
56 anwb->layerCount--;
57 if (anwb->layerCount == 0)
58 delete anwb;
59 }
60 }
61 struct FakeANativeWindowBuffer : public ANativeWindowBuffer {
FakeANativeWindowBufferFakeANativeWindowBuffer62 FakeANativeWindowBuffer() {
63 ANativeWindowBuffer();
64
65 common.incRef = incRefANWB;
66 common.decRef = decRefANWB;
67 layerCount = 0U;
68 }
69 };
70
incRefANW(android_native_base_t * base)71 static void incRefANW(android_native_base_t* base) {
72 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(base);
73 anw->oem[0]++;
74 }
75
decRefANW(android_native_base_t * base)76 static void decRefANW(android_native_base_t* base) {
77 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(base);
78 if (anw->oem[0] > 0) {
79 anw->oem[0]--;
80 if (anw->oem[0] == 0)
81 delete anw;
82 }
83 }
84
setSwapInterval(ANativeWindow *,int)85 static int setSwapInterval(ANativeWindow*, int) {
86 printf("%s: not implemented\n", __func__);
87 return 0;
88 }
89
dequeueBuffer_DEPRECATED(ANativeWindow * window,ANativeWindowBuffer ** buffer)90 static int dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer) {
91 if (!window->oem[1])
92 return -EINVAL;
93 *buffer = reinterpret_cast<ANativeWindowBuffer*>(window->oem[1]);
94 window->oem[1] = 0;
95 return 0;
96 }
97
lockBuffer_DEPRECATED(ANativeWindow *,ANativeWindowBuffer *)98 static int lockBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
99 printf("%s: not implemented\n", __func__);
100 return 0;
101 }
102
queueBuffer_DEPRECATED(ANativeWindow *,ANativeWindowBuffer *)103 static int queueBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
104 printf("%s: not implemented\n", __func__);
105 return 0;
106 }
107
query(const ANativeWindow * window,int what,int * value)108 static int query(const ANativeWindow* window, int what, int* value) {
109 switch (what) {
110 case NATIVE_WINDOW_WIDTH:
111 return static_cast<int>(window->oem[2]);
112 case NATIVE_WINDOW_HEIGHT:
113 return static_cast<int>(window->oem[3]);
114 default:
115 return -EINVAL;
116 }
117 }
118
perform(ANativeWindow *,int,...)119 static int perform(ANativeWindow*, int, ...) {
120 printf("%s: not implemented\n", __func__);
121 return 0;
122 }
123
cancelBuffer_DEPRECATED(ANativeWindow *,ANativeWindowBuffer *)124 static int cancelBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
125 printf("%s: not implemented\n", __func__);
126 return 0;
127 }
128
dequeueBuffer(ANativeWindow * window,ANativeWindowBuffer ** buffer,int * fenceFd)129 static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) {
130 *fenceFd = -1;
131 return dequeueBuffer_DEPRECATED(window, buffer);
132 }
133
queueBuffer(ANativeWindow * window,ANativeWindowBuffer * buffer,int fenceFd)134 static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
135 if (fenceFd >= 0)
136 close(fenceFd);
137 return queueBuffer_DEPRECATED(window, buffer);
138 }
139
cancelBuffer(ANativeWindow * window,ANativeWindowBuffer * buffer,int fenceFd)140 static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
141 if (fenceFd >= 0)
142 close(fenceFd);
143 return cancelBuffer_DEPRECATED(window, buffer);
144 }
145
146 struct FakeANativeWindow : public ANativeWindow {
FakeANativeWindowFakeANativeWindow147 FakeANativeWindow(uint32_t width, uint32_t height) {
148 ANativeWindow();
149
150 common.incRef = incRefANW;
151 common.decRef = decRefANW;
152 oem[0] = 0;
153 oem[2] = static_cast<intptr_t>(width);
154 oem[3] = static_cast<intptr_t>(height);
155
156 this->setSwapInterval = ::setSwapInterval;
157 this->dequeueBuffer_DEPRECATED = ::dequeueBuffer_DEPRECATED;
158 this->lockBuffer_DEPRECATED = ::lockBuffer_DEPRECATED;
159 this->queueBuffer_DEPRECATED = ::queueBuffer_DEPRECATED;
160 this->query = ::query;
161 this->perform = ::perform;
162 this->cancelBuffer_DEPRECATED = ::cancelBuffer_DEPRECATED;
163 this->dequeueBuffer = ::dequeueBuffer;
164 this->queueBuffer = ::queueBuffer;
165 this->cancelBuffer = ::cancelBuffer;
166 }
167 };
168
169 // Helpers
170
resourceToANWB(Resource * res)171 static ANativeWindowBuffer* resourceToANWB(Resource* res) {
172 ANativeWindowBuffer* buffer = new (std::nothrow) FakeANativeWindowBuffer();
173 if (!buffer)
174 return nullptr;
175
176 buffer->width = res->args.width;
177 buffer->height = res->args.height;
178 buffer->stride = res->args.width;
179 buffer->handle = reinterpret_cast<const native_handle_t*>(res->args.handle);
180 buffer->usage_deprecated = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
181 GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER;
182 buffer->usage =
183 GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN | GRALLOC1_CONSUMER_USAGE_CPU_WRITE_OFTEN |
184 GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE | GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN |
185 GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN | GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
186
187 switch (res->args.format) {
188 case VIRGL_FORMAT_B8G8R8A8_UNORM:
189 buffer->format = HAL_PIXEL_FORMAT_BGRA_8888;
190 break;
191 case VIRGL_FORMAT_B5G6R5_UNORM:
192 buffer->format = HAL_PIXEL_FORMAT_RGB_565;
193 break;
194 case VIRGL_FORMAT_R8G8B8A8_UNORM:
195 buffer->format = HAL_PIXEL_FORMAT_RGBA_8888;
196 break;
197 case VIRGL_FORMAT_R8G8B8X8_UNORM:
198 buffer->format = HAL_PIXEL_FORMAT_RGBX_8888;
199 break;
200 default:
201 delete buffer;
202 return nullptr;
203 }
204
205 return buffer;
206 }
207
208 // RenderControl
209
rcGetRendererVersion()210 static GLint rcGetRendererVersion() {
211 return 1; // seems to be hard-coded
212 }
213
rcGetEGLVersion(void * ctx_,EGLint * major,EGLint * minor)214 static EGLint rcGetEGLVersion(void* ctx_, EGLint* major, EGLint* minor) {
215 RenderControl* rc = static_cast<RenderControl*>(ctx_);
216 return s_egl.eglInitialize(rc->dpy, major, minor);
217 }
218
rcQueryEGLString(void * ctx_,EGLenum name,void * buffer,EGLint bufferSize)219 static EGLint rcQueryEGLString(void* ctx_, EGLenum name, void* buffer, EGLint bufferSize) {
220 RenderControl* rc = static_cast<RenderControl*>(ctx_);
221 const char* str = s_egl.eglQueryString(rc->dpy, name);
222 if (!str)
223 str = "";
224
225 if (strlen(str) > (size_t)bufferSize) {
226 memset(buffer, 0, bufferSize);
227 return -strlen(str);
228 }
229
230 char* strOut = static_cast<char*>(buffer);
231 strncpy(strOut, str, bufferSize - 1);
232 strOut[bufferSize - 1] = 0;
233
234 return strlen(strOut) + 1U;
235 }
236
replaceESVersionString(const std::string & prev,const char * const newver)237 static std::string replaceESVersionString(const std::string& prev, const char* const newver) {
238 // Do not touch ES 1.x contexts (they will all be 1.1 anyway)
239 if (prev.find("ES-CM") != std::string::npos)
240 return prev;
241
242 size_t esStart = prev.find("ES ");
243 size_t esEnd = prev.find(" ", esStart + 3);
244
245 // Do not change out-of-spec version strings.
246 if (esStart == std::string::npos || esEnd == std::string::npos)
247 return prev;
248
249 std::string res = prev.substr(0, esStart + 3);
250 res += newver;
251 res += prev.substr(esEnd);
252 return res;
253 }
254
rcGetGLString(void * ctx_,EGLenum name,void * buffer,EGLint bufferSize)255 static EGLint rcGetGLString(void* ctx_, EGLenum name, void* buffer, EGLint bufferSize) {
256 std::string glStr;
257
258 RenderControl* rc = static_cast<RenderControl*>(ctx_);
259 if (rc->ctx->ctx) {
260 const char* str = nullptr;
261 switch (rc->ctx->ctx->api) {
262 case EglContext::GLESApi::GLESApi_CM:
263 str = reinterpret_cast<const char*>(s_gles1.glGetString(name));
264 break;
265 default:
266 str = reinterpret_cast<const char*>(s_gles3.glGetString(name));
267 break;
268 }
269 if (str)
270 glStr += str;
271 }
272
273 // FIXME: Should probably filter the extensions list like the emulator
274 // does. We need to handle ES2 on ES3 compatibility for older
275 // Android versions, as well as filter out unsupported features.
276
277 if (name == GL_EXTENSIONS) {
278 glStr += ChecksumCalculator::getMaxVersionStr();
279 glStr += " ";
280
281 // FIXME: Hard-coded to 3.0 for now. We should attempt to detect 3.1.
282 glStr += "ANDROID_EMU_gles_max_version_3_0";
283 glStr += " ";
284 }
285
286 // FIXME: Add support for async swap and the fence_sync extensions
287
288 // We don't support GLDMA; use VIRTGPU_RESOURCE_CREATE and a combination of
289 // VIRTGPU_TRANSFER_TO_HOST and VIRTGPU_TRANSFER_FROM_HOST.
290
291 // FIXME: Add support for 'no host error'
292
293 if (name == GL_VERSION)
294 glStr = replaceESVersionString(glStr, "3.0");
295
296 int nextBufferSize = glStr.size() + 1;
297
298 if (!buffer || nextBufferSize > bufferSize)
299 return -nextBufferSize;
300
301 snprintf((char*)buffer, nextBufferSize, "%s", glStr.c_str());
302 return nextBufferSize;
303 }
304
rcGetNumConfigs(uint32_t * numAttribs)305 static EGLint rcGetNumConfigs(uint32_t* numAttribs) {
306 *numAttribs = EglConfig::kNumAttribs;
307 return EglConfig::vec.size();
308 }
309
rcGetConfigs(uint32_t bufSize,GLuint * buffer)310 static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer) {
311 size_t configAttribBytes = sizeof(EglConfig::kAttribs);
312 size_t nConfigs = EglConfig::vec.size();
313 size_t sizeNeeded = configAttribBytes + nConfigs * configAttribBytes;
314
315 if (bufSize < sizeNeeded)
316 return -sizeNeeded;
317
318 memcpy(buffer, &EglConfig::kAttribs, configAttribBytes);
319 size_t offset = EglConfig::kNumAttribs;
320 for (auto const& config : EglConfig::vec) {
321 memcpy(&buffer[offset], config->attribs, configAttribBytes);
322 offset += EglConfig::kNumAttribs;
323 }
324
325 return nConfigs;
326 }
327
rcChooseConfig(void * ctx_,EGLint * attribs,uint32_t,uint32_t * config_ints,uint32_t configs_size)328 static EGLint rcChooseConfig(void* ctx_, EGLint* attribs, uint32_t, uint32_t* config_ints,
329 uint32_t configs_size) {
330 EGLint num_config;
331 EGLConfig configs[configs_size];
332 RenderControl* rc = static_cast<RenderControl*>(ctx_);
333 EGLBoolean ret = s_egl.eglChooseConfig(rc->dpy, attribs, configs, configs_size, &num_config);
334 if (!ret)
335 num_config = 0;
336
337 if (configs_size) {
338 for (EGLint i = 0; i < num_config; i++) {
339 config_ints[i] = ~0U;
340 EGLint config_id;
341 if (s_egl.eglGetConfigAttrib(rc->dpy, configs[i], EGL_CONFIG_ID, &config_id)) {
342 for (size_t i = 0; i < EglConfig::vec.size(); i++) {
343 if (EglConfig::vec[i]->attribs[4] == config_id)
344 config_ints[i] = i;
345 }
346 }
347 if (config_ints[i] == ~0U) {
348 num_config = 0;
349 break;
350 }
351 }
352 if (!num_config)
353 memset(config_ints, 0, configs_size * sizeof(uint32_t));
354 }
355
356 return num_config;
357 }
358
rcGetFBParam(EGLint)359 static EGLint rcGetFBParam(EGLint) {
360 printf("%s: not implemented\n", __func__);
361 return 0;
362 }
363
rcCreateContext(void * ctx_,uint32_t config_,uint32_t share_,uint32_t glVersion)364 static uint32_t rcCreateContext(void* ctx_, uint32_t config_, uint32_t share_, uint32_t glVersion) {
365 // clang-format off
366 EGLint attrib_list[] = {
367 EGL_CONTEXT_CLIENT_VERSION, 0,
368 EGL_CONTEXT_MINOR_VERSION_KHR, 0,
369 EGL_NONE
370 };
371 // clang-format on
372 switch (glVersion) {
373 case EglContext::GLESApi::GLESApi_CM:
374 attrib_list[1] = 1;
375 attrib_list[3] = 1;
376 break;
377 case EglContext::GLESApi::GLESApi_2:
378 attrib_list[1] = 2;
379 break;
380 case EglContext::GLESApi::GLESApi_3_0:
381 attrib_list[1] = 3;
382 break;
383 case EglContext::GLESApi::GLESApi_3_1:
384 attrib_list[1] = 3;
385 attrib_list[3] = 1;
386 break;
387 }
388 if (!attrib_list[1])
389 return 0U;
390
391 if (config_ > EglConfig::vec.size())
392 return 0U;
393 EglConfig const* config = EglConfig::vec[config_];
394
395 EGLContext share_context = EGL_NO_CONTEXT;
396 if (share_ > 0) {
397 std::map<uint32_t, EglContext*>::iterator context_it;
398 context_it = EglContext::map.find(share_);
399 if (context_it == EglContext::map.end())
400 return 0U;
401
402 EglContext const* share = context_it->second;
403 share_context = share->context;
404 }
405
406 RenderControl* rc = static_cast<RenderControl*>(ctx_);
407 EGLContext context_ =
408 s_egl.eglCreateContext(rc->dpy, config->config, share_context, attrib_list);
409 if (context_ == EGL_NO_CONTEXT)
410 return 0U;
411
412 EglContext* context = new (std::nothrow)
413 EglContext(context_, rc->ctx->handle, (enum EglContext::GLESApi)glVersion);
414 if (!context) {
415 s_egl.eglDestroyContext(rc->dpy, context_);
416 return 0U;
417 }
418
419 return context->id;
420 }
421
rcDestroyContext(void * ctx_,uint32_t ctx)422 static void rcDestroyContext(void* ctx_, uint32_t ctx) {
423 std::map<uint32_t, EglContext*>::iterator it;
424 it = EglContext::map.find(ctx);
425 if (it == EglContext::map.end())
426 return;
427
428 EglContext* context = it->second;
429
430 RenderControl* rc = static_cast<RenderControl*>(ctx_);
431 s_egl.eglDestroyContext(rc->dpy, context->context);
432 context->context = EGL_NO_CONTEXT;
433 if (context->disposable())
434 delete context;
435 }
436
rcCreateWindowSurface(void * ctx_,uint32_t config_,uint32_t width,uint32_t height)437 static uint32_t rcCreateWindowSurface(void* ctx_, uint32_t config_, uint32_t width,
438 uint32_t height) {
439 if (config_ > EglConfig::vec.size())
440 return 0U;
441
442 EglConfig const* config = EglConfig::vec[config_];
443
444 RenderControl* rc = static_cast<RenderControl*>(ctx_);
445 EglSurface* surface =
446 new (std::nothrow) EglSurface(config->config, rc->ctx->handle, width, height);
447 if (!surface)
448 return 0U;
449
450 return surface->id;
451 }
452
rcDestroyWindowSurface(void * ctx_,uint32_t surface_)453 static void rcDestroyWindowSurface(void* ctx_, uint32_t surface_) {
454 std::map<uint32_t, EglSurface*>::iterator it;
455 it = EglSurface::map.find(surface_);
456 if (it == EglSurface::map.end())
457 return;
458
459 EglSurface* surface = it->second;
460
461 RenderControl* rc = static_cast<RenderControl*>(ctx_);
462 s_egl.eglDestroySurface(rc->dpy, surface->surface);
463 surface->surface = EGL_NO_SURFACE;
464 if (surface->disposable()) {
465 delete surface->window;
466 delete surface;
467 }
468 }
469
rcCreateColorBuffer(uint32_t,uint32_t,GLenum)470 static uint32_t rcCreateColorBuffer(uint32_t, uint32_t, GLenum) {
471 // NOTE: This CreateColorBuffer implementation is a no-op which returns a
472 // special surface ID to indicate that a pbuffer surface should be
473 // created. This is necessary because the emulator does not create a
474 // true pbuffer, it always creates a fake one. We don't want this.
475 return ~1U;
476 }
477
rcOpenColorBuffer(uint32_t)478 static void rcOpenColorBuffer(uint32_t) {
479 printf("%s: not implemented\n", __func__);
480 }
481
rcCloseColorBuffer(uint32_t)482 static void rcCloseColorBuffer(uint32_t) {
483 printf("%s: not implemented\n", __func__);
484 }
485
rcSetWindowColorBuffer(void * ctx_,uint32_t windowSurface,uint32_t colorBuffer)486 static void rcSetWindowColorBuffer(void* ctx_, uint32_t windowSurface, uint32_t colorBuffer) {
487 std::map<uint32_t, EglSurface*>::iterator surface_it;
488 surface_it = EglSurface::map.find(windowSurface);
489 if (surface_it == EglSurface::map.end())
490 return;
491
492 EglSurface* surface = surface_it->second;
493
494 RenderControl* rc = static_cast<RenderControl*>(ctx_);
495
496 if (colorBuffer == ~1U) {
497 EGLint const attrib_list[] = { EGL_WIDTH, (EGLint)surface->width, EGL_HEIGHT,
498 (EGLint)surface->height, EGL_NONE };
499 assert(surface->surface == EGL_NO_SURFACE && "Pbuffer set twice");
500 surface->surface = s_egl.eglCreatePbufferSurface(rc->dpy, surface->config, attrib_list);
501 } else {
502 std::map<uint32_t, Resource*>::iterator resource_it;
503 resource_it = Resource::map.find(colorBuffer);
504 if (resource_it == Resource::map.end())
505 return;
506
507 Resource* res = resource_it->second;
508 ANativeWindowBuffer* buffer = resourceToANWB(res);
509 if (!buffer)
510 return;
511
512 if (surface->surface == EGL_NO_SURFACE) {
513 surface->window =
514 new (std::nothrow) FakeANativeWindow(res->args.width, res->args.height);
515 if (!surface->window)
516 return;
517
518 NativeWindowType native_window = reinterpret_cast<NativeWindowType>(surface->window);
519 surface->window->oem[1] = (intptr_t)buffer;
520 surface->surface =
521 s_egl.eglCreateWindowSurface(rc->dpy, surface->config, native_window, nullptr);
522 } else {
523 surface->window->oem[1] = (intptr_t)buffer;
524 s_egl.eglSwapBuffers(rc->dpy, surface->surface);
525 }
526 }
527 }
528
rcFlushWindowColorBuffer(uint32_t windowSurface)529 static int rcFlushWindowColorBuffer(uint32_t windowSurface) {
530 std::map<uint32_t, EglSurface*>::iterator it;
531 it = EglSurface::map.find(windowSurface);
532 return it == EglSurface::map.end() ? -1 : 0;
533 }
534
rcMakeCurrent(void * ctx_,uint32_t context_,uint32_t drawSurf,uint32_t readSurf)535 static EGLint rcMakeCurrent(void* ctx_, uint32_t context_, uint32_t drawSurf, uint32_t readSurf) {
536 std::map<uint32_t, EglContext*>::iterator context_it;
537 context_it = EglContext::map.find(context_);
538 if (context_it == EglContext::map.end())
539 return EGL_FALSE;
540
541 EglContext* context = context_it->second;
542
543 std::map<uint32_t, EglSurface*>::iterator surface_it;
544 surface_it = EglSurface::map.find(drawSurf);
545 if (surface_it == EglSurface::map.end())
546 return EGL_FALSE;
547
548 EglSurface* draw_surface = surface_it->second;
549
550 surface_it = EglSurface::map.find(readSurf);
551 if (surface_it == EglSurface::map.end())
552 return EGL_FALSE;
553
554 EglSurface* read_surface = surface_it->second;
555
556 RenderControl* rc = static_cast<RenderControl*>(ctx_);
557
558 EglSurface* old_draw_surface = draw_surface->bind(rc->ctx->handle, false);
559 if (old_draw_surface)
560 old_draw_surface->unbind(false);
561
562 EglSurface* old_read_surface = read_surface->bind(rc->ctx->handle, true);
563 if (old_read_surface)
564 old_read_surface->unbind(true);
565
566 EglContext* old_context = context->bind(rc->ctx->handle);
567 if (old_context)
568 old_context->unbind();
569
570 EGLBoolean ret = s_egl.eglMakeCurrent(rc->dpy, draw_surface->surface, read_surface->surface,
571 context->context);
572 if (!ret) {
573 // If eglMakeCurrent fails, it's specified *not* to have unbound the
574 // previous contexts or surfaces, but many implementations do. This bug
575 // isn't worked around here, and we just assume the implementations obey
576 // the spec.
577 context->unbind();
578 if (old_context)
579 old_context->bind(rc->ctx->handle);
580 read_surface->unbind(true);
581 if (old_read_surface)
582 old_read_surface->bind(rc->ctx->handle, true);
583 draw_surface->unbind(false);
584 if (old_draw_surface)
585 old_draw_surface->bind(rc->ctx->handle, false);
586 } else {
587 if (old_context && old_context->disposable())
588 delete old_context;
589 if (old_read_surface && old_read_surface->disposable())
590 delete old_read_surface;
591 if (old_draw_surface && old_draw_surface->disposable())
592 delete old_draw_surface;
593 rc->ctx->unbind();
594 rc->ctx->bind(context);
595 }
596
597 return (EGLint)ret;
598 }
599
rcFBPost(uint32_t)600 static void rcFBPost(uint32_t) {
601 printf("%s: not implemented\n", __func__);
602 }
603
rcFBSetSwapInterval(void * ctx_,EGLint interval)604 static void rcFBSetSwapInterval(void* ctx_, EGLint interval) {
605 RenderControl* rc = static_cast<RenderControl*>(ctx_);
606 s_egl.eglSwapInterval(rc->dpy, interval);
607 }
608
rcBindTexture(void * ctx_,uint32_t colorBuffer)609 static void rcBindTexture(void* ctx_, uint32_t colorBuffer) {
610 std::map<uint32_t, Resource*>::iterator it;
611 it = Resource::map.find(colorBuffer);
612 if (it == Resource::map.end())
613 return;
614
615 RenderControl* rc = static_cast<RenderControl*>(ctx_);
616 Resource* res = it->second;
617 if (!res->image) {
618 ANativeWindowBuffer* buffer = resourceToANWB(res);
619 if (!buffer)
620 return;
621
622 EGLClientBuffer client_buffer = static_cast<EGLClientBuffer>(buffer);
623 EGLImageKHR image = s_egl.eglCreateImageKHR(
624 rc->dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, client_buffer, nullptr);
625 if (image == EGL_NO_IMAGE_KHR)
626 return;
627
628 EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
629 if (!img) {
630 s_egl.eglDestroyImageKHR(rc->dpy, image);
631 return;
632 }
633
634 // FIXME: House keeping, because we won't get asked to delete the image
635 // object otherwise, so we need to keep a reference to it..
636 res->image = img;
637 }
638
639 if (rc->ctx->ctx->api == EglContext::GLESApi::GLESApi_CM) {
640 // FIXME: Unconditional use of GL_TEXTURE_2D here is wrong
641 s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, res->image->image);
642 } else {
643 // FIXME: Unconditional use of GL_TEXTURE_2D here is wrong
644 s_gles3.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, res->image->image);
645 }
646 }
647
rcBindRenderbuffer(void * ctx_,uint32_t colorBuffer)648 static void rcBindRenderbuffer(void* ctx_, uint32_t colorBuffer) {
649 std::map<uint32_t, Resource*>::iterator it;
650 it = Resource::map.find(colorBuffer);
651 if (it == Resource::map.end())
652 return;
653
654 RenderControl* rc = static_cast<RenderControl*>(ctx_);
655 Resource* res = it->second;
656 if (!res->image) {
657 ANativeWindowBuffer* buffer = resourceToANWB(res);
658 if (!buffer)
659 return;
660
661 EGLClientBuffer client_buffer = static_cast<EGLClientBuffer>(buffer);
662 EGLImageKHR image = s_egl.eglCreateImageKHR(
663 rc->dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, client_buffer, nullptr);
664 if (image == EGL_NO_IMAGE_KHR)
665 return;
666
667 EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
668 if (!img) {
669 s_egl.eglDestroyImageKHR(rc->dpy, image);
670 return;
671 }
672
673 // FIXME: House keeping, because we won't get asked to delete the image
674 // object otherwise, so we need to keep a reference to it..
675 res->image = img;
676 }
677
678 if (rc->ctx->ctx->api == EglContext::GLESApi::GLESApi_CM) {
679 s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, res->image->image);
680 } else {
681 s_gles3.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, res->image->image);
682 }
683 }
684
rcColorBufferCacheFlush(uint32_t,EGLint,int)685 static EGLint rcColorBufferCacheFlush(uint32_t, EGLint, int) {
686 printf("%s: not implemented\n", __func__);
687 return 0;
688 }
689
rcReadColorBuffer(uint32_t,GLint,GLint,GLint,GLint,GLenum,GLenum,void *)690 static void rcReadColorBuffer(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*) {
691 printf("%s: not implemented\n", __func__);
692 }
693
rcUpdateColorBuffer(uint32_t,GLint,GLint,GLint,GLint,GLenum,GLenum,void *)694 static int rcUpdateColorBuffer(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*) {
695 printf("%s: not implemented\n", __func__);
696 return 0;
697 }
698
rcOpenColorBuffer2(uint32_t)699 static int rcOpenColorBuffer2(uint32_t) {
700 printf("%s: not implemented\n", __func__);
701 return 0;
702 }
703
rcCreateClientImage(void * ctx_,uint32_t context_,EGLenum target,GLuint buffer_)704 static uint32_t rcCreateClientImage(void* ctx_, uint32_t context_, EGLenum target, GLuint buffer_) {
705 std::map<uint32_t, EglContext*>::iterator it;
706 it = EglContext::map.find(context_);
707 if (it == EglContext::map.end())
708 return 0U;
709
710 EglContext* context = it->second;
711
712 RenderControl* rc = static_cast<RenderControl*>(ctx_);
713 EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(buffer_);
714 EGLImageKHR image = s_egl.eglCreateImageKHR(rc->dpy, context, target, buffer, nullptr);
715 EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
716 if (!img) {
717 s_egl.eglDestroyImageKHR(rc->dpy, image);
718 return 0U;
719 }
720
721 return img->id;
722 }
723
rcDestroyClientImage(uint32_t image_)724 static int rcDestroyClientImage(uint32_t image_) {
725 std::map<uint32_t, EglImage*>::iterator it;
726 it = EglImage::map.find(image_);
727 if (it == EglImage::map.end())
728 return EGL_FALSE;
729
730 EglImage* image = it->second;
731
732 delete image;
733 return EGL_TRUE;
734 }
735
rcSelectChecksumHelper(void * ctx_,uint32_t protocol,uint32_t)736 static void rcSelectChecksumHelper(void* ctx_, uint32_t protocol, uint32_t) {
737 RenderControl* rc = static_cast<RenderControl*>(ctx_);
738 rc->ctx->checksum_calc.setVersion(protocol);
739 }
740
rcCreateSyncKHR(void * ctx_,EGLenum type,EGLint * attribs,uint32_t,int,uint64_t * glsync_out,uint64_t * syncthread_out)741 static void rcCreateSyncKHR(void* ctx_, EGLenum type, EGLint* attribs, uint32_t, int,
742 uint64_t* glsync_out, uint64_t* syncthread_out) {
743 *syncthread_out = 0ULL;
744
745 RenderControl* rc = static_cast<RenderControl*>(ctx_);
746 EGLSyncKHR sync = s_egl.eglCreateSyncKHR(rc->dpy, type, attribs);
747 if (sync == EGL_NO_SYNC_KHR) {
748 *glsync_out = 0ULL;
749 return;
750 }
751
752 EglSync* syn = new (std::nothrow) EglSync(sync);
753 if (!syn) {
754 s_egl.eglDestroySyncKHR(rc->dpy, sync);
755 *glsync_out = 0ULL;
756 return;
757 }
758
759 *glsync_out = syn->id;
760 }
761
rcClientWaitSyncKHR(void * ctx_,uint64_t sync_,EGLint flags,uint64_t timeout)762 static EGLint rcClientWaitSyncKHR(void* ctx_, uint64_t sync_, EGLint flags, uint64_t timeout) {
763 std::map<uint64_t, EglSync*>::iterator it;
764 it = EglSync::map.find(sync_);
765 if (it == EglSync::map.end())
766 return EGL_CONDITION_SATISFIED_KHR;
767
768 EglSync* sync = it->second;
769 RenderControl* rc = static_cast<RenderControl*>(ctx_);
770 return s_egl.eglClientWaitSyncKHR(rc->dpy, sync->sync, flags, timeout);
771 }
772
rcFlushWindowColorBufferAsync(uint32_t windowSurface)773 static void rcFlushWindowColorBufferAsync(uint32_t windowSurface) {
774 // No-op
775 }
776
rcDestroySyncKHR(void * ctx_,uint64_t sync_)777 static int rcDestroySyncKHR(void* ctx_, uint64_t sync_) {
778 std::map<uint64_t, EglSync*>::iterator it;
779 it = EglSync::map.find(sync_);
780 if (it == EglSync::map.end())
781 return EGL_FALSE;
782
783 EglSync* sync = it->second;
784 RenderControl* rc = static_cast<RenderControl*>(ctx_);
785 return s_egl.eglDestroySyncKHR(rc->dpy, sync->sync);
786 }
787
rcSetPuid(void * ctx_,uint64_t proto)788 static void rcSetPuid(void* ctx_, uint64_t proto) {
789 union {
790 uint64_t proto;
791 struct {
792 int pid;
793 int tid;
794 } id;
795 } puid;
796
797 puid.proto = proto;
798
799 RenderControl* rc = static_cast<RenderControl*>(ctx_);
800 rc->ctx->setPidTid(puid.id.pid, puid.id.tid);
801 }
802
rcUpdateColorBufferDMA(uint32_t,GLint,GLint,GLint,GLint,GLenum,GLenum,void *,uint32_t)803 static int rcUpdateColorBufferDMA(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*,
804 uint32_t) {
805 printf("%s: not implemented\n", __func__);
806 return 0;
807 }
808
rcCreateColorBufferDMA(uint32_t,uint32_t,GLenum,int)809 static uint32_t rcCreateColorBufferDMA(uint32_t, uint32_t, GLenum, int) {
810 printf("%s: not implemented\n", __func__);
811 return 0U;
812 }
813
rcWaitSyncKHR(void * ctx_,uint64_t sync_,EGLint flags)814 static void rcWaitSyncKHR(void* ctx_, uint64_t sync_, EGLint flags) {
815 std::map<uint64_t, EglSync*>::iterator it;
816 it = EglSync::map.find(sync_);
817 if (it == EglSync::map.end())
818 return;
819
820 EglSync* sync = it->second;
821 RenderControl* rc = static_cast<RenderControl*>(ctx_);
822 // FIXME: No eglWaitSyncKHR support in SwiftShader
823 // This call will BLOCK when it should be asynchronous!
824 s_egl.eglClientWaitSyncKHR(rc->dpy, sync->sync, flags, EGL_FOREVER_KHR);
825 }
826
RenderControl(Context * ctx_,EGLDisplay dpy_)827 RenderControl::RenderControl(Context* ctx_, EGLDisplay dpy_) {
828 rcGetRendererVersion = ::rcGetRendererVersion;
829 rcGetEGLVersion_dec = ::rcGetEGLVersion;
830 rcQueryEGLString_dec = ::rcQueryEGLString;
831 rcGetGLString_dec = ::rcGetGLString;
832 rcGetNumConfigs = ::rcGetNumConfigs;
833 rcGetConfigs = ::rcGetConfigs;
834 rcChooseConfig_dec = ::rcChooseConfig;
835 rcGetFBParam = ::rcGetFBParam;
836 rcCreateContext_dec = ::rcCreateContext;
837 rcDestroyContext_dec = ::rcDestroyContext;
838 rcCreateWindowSurface_dec = ::rcCreateWindowSurface;
839 rcDestroyWindowSurface_dec = ::rcDestroyWindowSurface;
840 rcCreateColorBuffer = ::rcCreateColorBuffer;
841 rcOpenColorBuffer = ::rcOpenColorBuffer;
842 rcCloseColorBuffer = ::rcCloseColorBuffer;
843 rcSetWindowColorBuffer_dec = ::rcSetWindowColorBuffer;
844 rcFlushWindowColorBuffer = ::rcFlushWindowColorBuffer;
845 rcMakeCurrent_dec = ::rcMakeCurrent;
846 rcFBPost = ::rcFBPost;
847 rcFBSetSwapInterval_dec = ::rcFBSetSwapInterval;
848 rcBindTexture_dec = ::rcBindTexture;
849 rcBindRenderbuffer_dec = ::rcBindRenderbuffer;
850 rcColorBufferCacheFlush = ::rcColorBufferCacheFlush;
851 rcReadColorBuffer = ::rcReadColorBuffer;
852 rcUpdateColorBuffer = ::rcUpdateColorBuffer;
853 rcOpenColorBuffer2 = ::rcOpenColorBuffer2;
854 rcCreateClientImage_dec = ::rcCreateClientImage;
855 rcDestroyClientImage = ::rcDestroyClientImage;
856 rcSelectChecksumHelper_dec = ::rcSelectChecksumHelper;
857 rcCreateSyncKHR_dec = ::rcCreateSyncKHR;
858 rcClientWaitSyncKHR_dec = ::rcClientWaitSyncKHR;
859 rcFlushWindowColorBufferAsync = ::rcFlushWindowColorBufferAsync;
860 rcDestroySyncKHR_dec = ::rcDestroySyncKHR;
861 rcSetPuid_dec = ::rcSetPuid;
862 rcUpdateColorBufferDMA = ::rcUpdateColorBufferDMA;
863 rcCreateColorBufferDMA = ::rcCreateColorBufferDMA;
864 rcWaitSyncKHR_dec = ::rcWaitSyncKHR;
865
866 dpy = dpy_;
867 ctx = ctx_;
868 }
869