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 48 static void incRefANWB(android_native_base_t* base) { 49 ANativeWindowBuffer* anwb = reinterpret_cast<ANativeWindowBuffer*>(base); 50 anwb->layerCount++; 51 } 52 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 { 62 FakeANativeWindowBuffer() { 63 ANativeWindowBuffer(); 64 65 common.incRef = incRefANWB; 66 common.decRef = decRefANWB; 67 layerCount = 0U; 68 } 69 }; 70 71 static void incRefANW(android_native_base_t* base) { 72 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(base); 73 anw->oem[0]++; 74 } 75 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 85 static int setSwapInterval(ANativeWindow*, int) { 86 printf("%s: not implemented\n", __func__); 87 return 0; 88 } 89 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 98 static int lockBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) { 99 printf("%s: not implemented\n", __func__); 100 return 0; 101 } 102 103 static int queueBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) { 104 printf("%s: not implemented\n", __func__); 105 return 0; 106 } 107 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 119 static int perform(ANativeWindow*, int, ...) { 120 printf("%s: not implemented\n", __func__); 121 return 0; 122 } 123 124 static int cancelBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) { 125 printf("%s: not implemented\n", __func__); 126 return 0; 127 } 128 129 static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) { 130 *fenceFd = -1; 131 return dequeueBuffer_DEPRECATED(window, buffer); 132 } 133 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 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 { 147 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 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 210 static GLint rcGetRendererVersion() { 211 return 1; // seems to be hard-coded 212 } 213 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 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 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 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 305 static EGLint rcGetNumConfigs(uint32_t* numAttribs) { 306 *numAttribs = EglConfig::kNumAttribs; 307 return EglConfig::vec.size(); 308 } 309 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 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 359 static EGLint rcGetFBParam(EGLint) { 360 printf("%s: not implemented\n", __func__); 361 return 0; 362 } 363 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 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 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 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 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 478 static void rcOpenColorBuffer(uint32_t) { 479 printf("%s: not implemented\n", __func__); 480 } 481 482 static void rcCloseColorBuffer(uint32_t) { 483 printf("%s: not implemented\n", __func__); 484 } 485 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 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 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 600 static void rcFBPost(uint32_t) { 601 printf("%s: not implemented\n", __func__); 602 } 603 604 static void rcFBSetSwapInterval(void* ctx_, EGLint interval) { 605 RenderControl* rc = static_cast<RenderControl*>(ctx_); 606 s_egl.eglSwapInterval(rc->dpy, interval); 607 } 608 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 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 685 static EGLint rcColorBufferCacheFlush(uint32_t, EGLint, int) { 686 printf("%s: not implemented\n", __func__); 687 return 0; 688 } 689 690 static void rcReadColorBuffer(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*) { 691 printf("%s: not implemented\n", __func__); 692 } 693 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 699 static int rcOpenColorBuffer2(uint32_t) { 700 printf("%s: not implemented\n", __func__); 701 return 0; 702 } 703 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 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 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 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 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 773 static void rcFlushWindowColorBufferAsync(uint32_t windowSurface) { 774 // No-op 775 } 776 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 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 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 809 static uint32_t rcCreateColorBufferDMA(uint32_t, uint32_t, GLenum, int) { 810 printf("%s: not implemented\n", __func__); 811 return 0U; 812 } 813 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 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