• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 extern "C" {
19 #include <linux/virtio_gpu.h>
20 #include <virglrenderer.h>
21 #include <virgl_hw.h>
22 }
23 
24 #include <sys/uio.h>
25 
26 #include <dlfcn.h>
27 #include <algorithm>
28 #include <cassert>
29 #include <cerrno>
30 #include <cstdio>
31 #include <cstdlib>
32 #include <cstring>
33 #include <deque>
34 #include <map>
35 #include <mutex>
36 #include <string>
37 #include <vector>
38 
39 #include <EGL/egl.h>
40 #include <EGL/eglext.h>
41 #include <GLES/gl.h>
42 #include <GLES/glext.h>
43 #include <GLES3/gl31.h>
44 #include <GLES3/gl3ext.h>
45 
46 #include <drm/drm_fourcc.h>
47 
48 #include <OpenGLESDispatch/EGLDispatch.h>
49 #include <OpenGLESDispatch/GLESv1Dispatch.h>
50 #include <OpenGLESDispatch/GLESv3Dispatch.h>
51 
52 #include "OpenglRender/IOStream.h"
53 
54 #include "Context.h"
55 #include "EglConfig.h"
56 #include "EglContext.h"
57 #include "EglSurface.h"
58 #include "EglSync.h"
59 #include "Resource.h"
60 
61 #include <VirtioGpuCmd.h>
62 
63 // for debug only
64 #include <sys/syscall.h>
65 #include <unistd.h>
66 #define gettid() (int)syscall(__NR_gettid)
67 
68 #ifndef PAGE_SIZE
69 #define PAGE_SIZE 0x1000
70 #endif
71 
72 #define MAX_CMDRESPBUF_SIZE (10 * PAGE_SIZE)
73 
74 #define ALIGN(A, B) (((A) + (B)-1) / (B) * (B))
75 
76 // Enable passing scanout buffers as texture names to sdl2 backend
77 #define QEMU_HARDWARE_GL_INTEROP
78 
79 #ifdef QEMU_HARDWARE_GL_INTEROP
80 typedef GLenum (*PFNGLGETERROR)(void);
81 typedef void (*PFNGLBINDTEXTURE)(GLenum target, GLuint texture);
82 typedef void (*PFNGLGENTEXTURES)(GLsizei n, GLuint* textures);
83 typedef void (*PFNGLTEXPARAMETERI)(GLenum target, GLenum pname, GLint param);
84 typedef void (*PFNGLPIXELSTOREI)(GLenum pname, GLint param);
85 typedef void (*PFNGLTEXIMAGE2D)(GLenum target, GLint level, GLint internalformat, GLsizei width,
86                                 GLsizei height, GLint border, GLenum format, GLenum type,
87                                 const void* pixels);
88 static PFNGLBINDTEXTURE g_glBindTexture;
89 static PFNGLGENTEXTURES g_glGenTextures;
90 static PFNGLTEXPARAMETERI g_glTexParameteri;
91 static PFNGLPIXELSTOREI g_glPixelStorei;
92 static PFNGLTEXIMAGE2D g_glTexImage2D;
93 static virgl_renderer_gl_context g_ctx0_alt;
94 #endif
95 
96 // Global state
97 std::map<uint32_t, EglContext*> EglContext::map;
98 std::map<uint32_t, EglSurface*> EglSurface::map;
99 std::map<uint32_t, EglImage*> EglImage::map;
100 std::map<uint32_t, Resource*> Resource::map;
101 std::map<uint64_t, EglSync*> EglSync::map;
102 std::map<uint32_t, Context*> Context::map;
103 std::vector<EglConfig*> EglConfig::vec;
104 static virgl_renderer_callbacks* g_cb;
105 const EGLint EglConfig::kAttribs[];
106 uint32_t EglContext::nextId = 1U;
107 uint32_t EglSurface::nextId = 1U;
108 uint32_t EglImage::nextId = 1U;
109 uint64_t EglSync::nextId = 1U;
110 static void* g_cookie;
111 
112 // Fence queue, must be thread safe
113 static std::mutex g_fence_deque_mutex;
114 static std::deque<int> g_fence_deque;
115 
116 // Other GPU context and state
117 static EGLSurface g_ctx0_surface;
118 static EGLContext g_ctx0_es1;
119 static EGLContext g_ctx0_es2;
120 static EGLDisplay g_dpy;
121 
122 // Last context receiving a command. Allows us to find the context a fence is
123 // being created for. Works around the poorly designed virgl interface.
124 static Context* g_last_submit_cmd_ctx;
125 
126 #ifdef OPENGL_DEBUG_PRINTOUT
127 
128 #include "emugl/common/logging.h"
129 
130 // For logging from the protocol decoders
131 
default_logger(const char * fmt,...)132 void default_logger(const char* fmt, ...) {
133     va_list ap;
134     va_start(ap, fmt);
135     vprintf(fmt, ap);
136     va_end(ap);
137 }
138 
139 emugl_logger_t emugl_cxt_logger = default_logger;
140 
141 #endif
142 
dump_global_state(void)143 static void dump_global_state(void) {
144     printf("AVDVIRGLRENDERER GLOBAL STATE\n\n");
145 
146     printf("Resources:\n");
147     for (auto const& it : Resource::map) {
148         Resource const* res = it.second;
149 
150         printf(
151             "  Resource %u: %ux%u 0x%x %p (%zub) t=%u b=%u d=%u a=%u l=%u "
152             "n=%u f=%u\n",
153             res->args.handle, res->args.width, res->args.height, res->args.format,
154             res->iov ? res->iov[0].iov_base : nullptr, res->iov ? res->iov[0].iov_len : 0,
155             res->args.target, res->args.bind, res->args.depth, res->args.array_size,
156             res->args.last_level, res->args.nr_samples, res->args.flags);
157 
158         for (auto const& it : res->context_map) {
159             Context const* ctx = it.second;
160 
161             printf("    Context %u, pid=%d, tid=%d\n", ctx->handle, ctx->pid, ctx->tid);
162         }
163     }
164 
165     printf("Contexts:\n");
166     for (auto const& it : Context::map) {
167         Context const* ctx = it.second;
168 
169         printf("  Context %u: %s pid=%u tid=%u\n", ctx->handle, ctx->name.c_str(), ctx->pid,
170                ctx->tid);
171 
172         for (auto const& it : ctx->resource_map) {
173             Resource const* res = it.second;
174 
175             printf("    Resource %u\n", res->args.handle);
176         }
177     }
178 }
179 
sync_linear_to_iovec(Resource * res,uint64_t offset,const virgl_box * box)180 static int sync_linear_to_iovec(Resource* res, uint64_t offset, const virgl_box* box) {
181     uint32_t bpp;
182     switch (res->args.format) {
183         case VIRGL_FORMAT_R8_UNORM:
184             bpp = 1U;
185             break;
186         case VIRGL_FORMAT_B5G6R5_UNORM:
187             bpp = 2U;
188             break;
189         default:
190             bpp = 4U;
191             break;
192     }
193 
194     if (box->x > res->args.width || box->y > res->args.height)
195         return 0;
196     if (box->w == 0U || box->h == 0U)
197         return 0;
198     uint32_t w = std::min(box->w, res->args.width - box->x);
199     uint32_t h = std::min(box->h, res->args.height - box->y);
200     uint32_t stride = ALIGN(res->args.width * bpp, 16U);
201     offset += box->y * stride + box->x * bpp;
202     size_t length = (h - 1U) * stride + w * bpp;
203     if (offset + length > res->linearSize)
204         return EINVAL;
205 
206     if (res->num_iovs > 1) {
207         const char* linear = static_cast<const char*>(res->linear);
208         for (uint32_t i = 0, iovOffset = 0U; length && i < res->num_iovs; i++) {
209             if (iovOffset + res->iov[i].iov_len > offset) {
210                 char* iov_base = static_cast<char*>(res->iov[i].iov_base);
211                 size_t copyLength = std::min(length, res->iov[i].iov_len);
212                 memcpy(iov_base + offset - iovOffset, linear, copyLength);
213                 linear += copyLength;
214                 offset += copyLength;
215                 length -= copyLength;
216             }
217             iovOffset += res->iov[i].iov_len;
218         }
219     }
220 
221     return 0;
222 }
223 
sync_iovec_to_linear(Resource * res,uint64_t offset,const virgl_box * box)224 static int sync_iovec_to_linear(Resource* res, uint64_t offset, const virgl_box* box) {
225     uint32_t bpp;
226     switch (res->args.format) {
227         case VIRGL_FORMAT_R8_UNORM:
228             bpp = 1U;
229             break;
230         case VIRGL_FORMAT_B5G6R5_UNORM:
231             bpp = 2U;
232             break;
233         default:
234             bpp = 4U;
235             break;
236     }
237 
238     if (box->x > res->args.width || box->y > res->args.height)
239         return 0;
240     if (box->w == 0U || box->h == 0U)
241         return 0;
242     uint32_t w = std::min(box->w, res->args.width - box->x);
243     uint32_t h = std::min(box->h, res->args.height - box->y);
244     uint32_t stride = ALIGN(res->args.width * bpp, 16U);
245     offset += box->y * stride + box->x * bpp;
246     size_t length = (h - 1U) * stride + w * bpp;
247     if (offset + length > res->linearSize)
248         return EINVAL;
249 
250     if (res->num_iovs > 1) {
251         char* linear = static_cast<char*>(res->linear);
252         for (uint32_t i = 0, iovOffset = 0U; length && i < res->num_iovs; i++) {
253             if (iovOffset + res->iov[i].iov_len > offset) {
254                 const char* iov_base = static_cast<const char*>(res->iov[i].iov_base);
255                 size_t copyLength = std::min(length, res->iov[i].iov_len);
256                 memcpy(linear, iov_base + offset - iovOffset, copyLength);
257                 linear += copyLength;
258                 offset += copyLength;
259                 length -= copyLength;
260             }
261             iovOffset += res->iov[i].iov_len;
262         }
263     }
264 
265     return 0;
266 }
267 
268 // The below API was defined by virglrenderer 'master', but does not seem to
269 // be used by QEMU, so just ignore it for now..
270 //
271 // virgl_renderer_get_rect
272 // virgl_renderer_get_fd_for_texture
273 // virgl_renderer_cleanup
274 // virgl_renderer_reset
275 // virgl_renderer_get_poll_fd
276 
virgl_renderer_init(void * cookie,int flags,virgl_renderer_callbacks * cb)277 int virgl_renderer_init(void* cookie, int flags, virgl_renderer_callbacks* cb) {
278     if (!cookie || !cb)
279         return EINVAL;
280 
281     if (flags != 0)
282         return ENOSYS;
283 
284     if (cb->version != 1)
285         return ENOSYS;
286 
287 #ifdef QEMU_HARDWARE_GL_INTEROP
288     // FIXME: If we just use "libGL.so" here, mesa's interception library returns
289     //        stub dlsyms that do nothing at runtime, even after binding..
290     void* handle = dlopen(
291         "/usr/lib/x86_64-linux-gnu/nvidia/"
292         "current/libGL.so.384.111",
293         RTLD_NOW);
294     assert(handle != nullptr);
295     g_glBindTexture = (PFNGLBINDTEXTURE)dlsym(handle, "glBindTexture");
296     assert(g_glBindTexture != nullptr);
297     g_glGenTextures = (PFNGLGENTEXTURES)dlsym(handle, "glGenTextures");
298     assert(g_glGenTextures != nullptr);
299     g_glTexParameteri = (PFNGLTEXPARAMETERI)dlsym(handle, "glTexParameteri");
300     assert(g_glTexParameteri != nullptr);
301     g_glPixelStorei = (PFNGLPIXELSTOREI)dlsym(handle, "glPixelStorei");
302     assert(g_glPixelStorei != nullptr);
303     g_glTexImage2D = (PFNGLTEXIMAGE2D)dlsym(handle, "glTexImage2D");
304     assert(g_glTexImage2D != nullptr);
305 #endif
306 
307     if (!egl_dispatch_init())
308         return ENOENT;
309 
310     if (!gles1_dispatch_init())
311         return ENOENT;
312 
313     if (!gles3_dispatch_init())
314         return ENOENT;
315 
316     g_dpy = s_egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
317     if (g_dpy == EGL_NO_DISPLAY) {
318         printf("Failed to open default EGL display\n");
319         return ENOENT;
320     }
321 
322     if (!s_egl.eglInitialize(g_dpy, nullptr, nullptr)) {
323         printf("Failed to initialize EGL display\n");
324         g_dpy = EGL_NO_DISPLAY;
325         return ENOENT;
326     }
327 
328     EGLint nConfigs;
329     if (!s_egl.eglGetConfigs(g_dpy, nullptr, 0, &nConfigs)) {
330         printf("Failed to retrieve number of EGL configs\n");
331         s_egl.eglTerminate(g_dpy);
332         g_dpy = EGL_NO_DISPLAY;
333         return ENOENT;
334     }
335 
336     EGLConfig configs[nConfigs];
337     if (!s_egl.eglGetConfigs(g_dpy, configs, nConfigs, &nConfigs)) {
338         printf("Failed to retrieve EGL configs\n");
339         s_egl.eglTerminate(g_dpy);
340         g_dpy = EGL_NO_DISPLAY;
341         return ENOENT;
342     }
343 
344     // Our static analyzer sees the `new`ing of `config` below without any sort
345     // of attempt to free it, and warns about it. Normally, it would catch that
346     // we're pushing it into a vector in the constructor, but it hits an
347     // internal evaluation limit when trying to evaluate the loop inside of the
348     // ctor. So, it never gets to see that we escape our newly-allocated
349     // `config` instance. Silence the warning, since it's incorrect.
350     // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
351     for (EGLint c = 0; c < nConfigs; c++) {
352         EGLint configId;
353         if (!s_egl.eglGetConfigAttrib(g_dpy, configs[c], EGL_CONFIG_ID, &configId)) {
354             printf("Failed to retrieve EGL config ID\n");
355             s_egl.eglTerminate(g_dpy);
356             g_dpy = EGL_NO_DISPLAY;
357             return ENOENT;
358         }
359         EglConfig* config =
360             new (std::nothrow) EglConfig(g_dpy, configs[c], s_egl.eglGetConfigAttrib);
361         if (!config)
362             return ENOMEM;
363     }
364 
365     // clang-format off
366     EGLint const attrib_list[] = {
367         EGL_CONFORMANT,   EGL_OPENGL_ES_BIT | EGL_OPENGL_ES3_BIT_KHR,
368         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
369         EGL_NONE,
370      };
371     // clang-format on
372     EGLint num_config = 0;
373     EGLConfig config;
374     if (!s_egl.eglChooseConfig(g_dpy, attrib_list, &config, 1, &num_config) || num_config != 1) {
375         printf("Failed to select ES1 & ES3 capable EGL config\n");
376         s_egl.eglTerminate(g_dpy);
377         g_dpy = EGL_NO_DISPLAY;
378         return ENOENT;
379     }
380 
381     // clang-format off
382     EGLint const pbuffer_attrib_list[] = {
383         EGL_WIDTH,  1,
384         EGL_HEIGHT, 1,
385         EGL_NONE
386     };
387     // clang-format on
388     g_ctx0_surface = s_egl.eglCreatePbufferSurface(g_dpy, config, pbuffer_attrib_list);
389     if (!g_ctx0_surface) {
390         printf("Failed to create pbuffer surface for context 0\n");
391         s_egl.eglTerminate(g_dpy);
392         g_dpy = EGL_NO_DISPLAY;
393         return ENOENT;
394     }
395 
396     // clang-format off
397     EGLint const es1_attrib_list[] = {
398         EGL_CONTEXT_CLIENT_VERSION, 1,
399         EGL_NONE
400     };
401     // clang-format on
402     g_ctx0_es1 = s_egl.eglCreateContext(g_dpy, config, EGL_NO_CONTEXT, es1_attrib_list);
403     if (g_ctx0_es1 == EGL_NO_CONTEXT) {
404         printf("Failed to create ES1 context 0\n");
405         s_egl.eglDestroySurface(g_dpy, g_ctx0_surface);
406         s_egl.eglTerminate(g_dpy);
407         g_dpy = EGL_NO_DISPLAY;
408         return ENOENT;
409     }
410 
411     // clang-format off
412     EGLint const es2_attrib_list[] = {
413         EGL_CONTEXT_CLIENT_VERSION, 3, // yes, 3
414         EGL_NONE
415     };
416     // clang-format on
417     g_ctx0_es2 = s_egl.eglCreateContext(g_dpy, config, EGL_NO_CONTEXT, es2_attrib_list);
418     if (g_ctx0_es2 == EGL_NO_CONTEXT) {
419         printf("Failed to create ES2 context 0\n");
420         s_egl.eglDestroySurface(g_dpy, g_ctx0_surface);
421         s_egl.eglDestroyContext(g_dpy, g_ctx0_es1);
422         g_ctx0_es1 = EGL_NO_CONTEXT;
423         s_egl.eglTerminate(g_dpy);
424         g_dpy = EGL_NO_DISPLAY;
425     }
426 
427 #ifdef QEMU_HARDWARE_GL_INTEROP
428     // This is the hardware GPU context. In future, this code should probably
429     // be removed and SwiftShader be used for all presentation blits.
430     virgl_renderer_gl_ctx_param ctx_params = {
431         .major_ver = 3,
432         .minor_ver = 0,
433     };
434     g_ctx0_alt = cb->create_gl_context(cookie, 0, &ctx_params);
435     if (!g_ctx0_alt) {
436         printf("Failed to create hardware GL context 0\n");
437         s_egl.eglDestroySurface(g_dpy, g_ctx0_surface);
438         s_egl.eglDestroyContext(g_dpy, g_ctx0_es1);
439         g_ctx0_es1 = EGL_NO_CONTEXT;
440         s_egl.eglTerminate(g_dpy);
441         g_dpy = EGL_NO_DISPLAY;
442     }
443 
444     // Test we can actually make it current; otherwise, bail
445     if (cb->make_current(cookie, 0, g_ctx0_alt)) {
446         printf("Failed to make hardware GL context 0 current\n");
447         cb->destroy_gl_context(cookie, g_ctx0_alt);
448         g_ctx0_alt = nullptr;
449         s_egl.eglDestroySurface(g_dpy, g_ctx0_surface);
450         s_egl.eglDestroyContext(g_dpy, g_ctx0_es1);
451         g_ctx0_es1 = EGL_NO_CONTEXT;
452         s_egl.eglTerminate(g_dpy);
453         g_dpy = EGL_NO_DISPLAY;
454     }
455 #endif
456 
457     EglContext::nextId = 1U;
458     g_cookie = cookie;
459     g_cb = cb;
460     return 0;
461 }
462 
virgl_renderer_poll(void)463 void virgl_renderer_poll(void) {
464     std::lock_guard<std::mutex> lk(g_fence_deque_mutex);
465     for (auto fence : g_fence_deque)
466         g_cb->write_fence(g_cookie, fence);
467     g_fence_deque.clear();
468 }
469 
virgl_renderer_get_cursor_data(uint32_t resource_id,uint32_t * width,uint32_t * height)470 void* virgl_renderer_get_cursor_data(uint32_t resource_id, uint32_t* width, uint32_t* height) {
471     if (!width || !height)
472         return nullptr;
473 
474     std::map<uint32_t, Resource*>::iterator it;
475     it = Resource::map.find(resource_id);
476     if (it == Resource::map.end())
477         return nullptr;
478 
479     Resource* res = it->second;
480     if (res->args.bind != VIRGL_RES_BIND_CURSOR)
481         return nullptr;
482 
483     void* pixels = malloc(res->linearSize);
484     memcpy(pixels, res->linear, res->linearSize);
485     *height = res->args.height;
486     *width = res->args.width;
487     return pixels;
488 }
489 
490 // NOTE: This function is called from thread context. Do not touch anything
491 // without a mutex to protect it from concurrent access. Everything else in
492 // libvirglrenderer is designed to be single-threaded *only*.
493 
494 // Hack to serialize all calls into EGL or GLES functions due to bugs in
495 // swiftshader. This should be removed as soon as possible.
496 static std::mutex swiftshader_wa_mutex;
497 
process_cmd(Context * ctx,char * buf,size_t bufSize,int fence)498 static void process_cmd(Context* ctx, char* buf, size_t bufSize, int fence) {
499     VirtioGpuCmd* cmd_resp = reinterpret_cast<VirtioGpuCmd*>(ctx->cmd_resp->linear);
500 
501     IOStream stream(cmd_resp->buf, MAX_CMDRESPBUF_SIZE - sizeof(*cmd_resp));
502 
503     {
504         std::lock_guard<std::mutex> lk(swiftshader_wa_mutex);
505         size_t decodedBytes;
506 
507         decodedBytes = ctx->render_control.decode(buf, bufSize, &stream, &ctx->checksum_calc);
508         bufSize -= decodedBytes;
509         buf += decodedBytes;
510 
511         decodedBytes = ctx->gles1.decode(buf, bufSize, &stream, &ctx->checksum_calc);
512         bufSize -= decodedBytes;
513         buf += decodedBytes;
514 
515         decodedBytes = ctx->gles3.decode(buf, bufSize, &stream, &ctx->checksum_calc);
516         bufSize -= decodedBytes;
517         buf += decodedBytes;
518     }
519 
520     assert(bufSize == 0);
521 
522     cmd_resp->cmdSize += stream.getFlushSize();
523 
524     printf("(tid %d) ctx %d: cmd %u, size %zu, fence %d\n", gettid(), ctx->handle, cmd_resp->op,
525            cmd_resp->cmdSize - sizeof(*cmd_resp), fence);
526     if (cmd_resp->cmdSize - sizeof(*cmd_resp) > 0) {
527         printf("(tid %d) ", gettid());
528         for (size_t i = 0; i < cmd_resp->cmdSize - sizeof(*cmd_resp); i++) {
529             printf("%.2x ", (unsigned char)cmd_resp->buf[i]);
530         }
531         printf("\n");
532     }
533 
534     virgl_box box = {
535         .w = cmd_resp->cmdSize,
536         .h = 1,
537     };
538     sync_linear_to_iovec(ctx->cmd_resp, 0, &box);
539 
540     {
541         std::lock_guard<std::mutex> lk(g_fence_deque_mutex);
542         g_fence_deque.push_back(fence);
543     }
544 }
545 
virgl_renderer_submit_cmd(void * buffer,int ctx_id,int ndw)546 int virgl_renderer_submit_cmd(void* buffer, int ctx_id, int ndw) {
547     VirtioGpuCmd* cmd = static_cast<VirtioGpuCmd*>(buffer);
548     size_t bufSize = sizeof(uint32_t) * ndw;
549 
550     if (bufSize < sizeof(*cmd)) {
551         printf("bad buffer size, bufSize=%zu, ctx=%d\n", bufSize, ctx_id);
552         return -1;
553     }
554 
555     printf("ctx %d: cmd %u, size %zu\n", ctx_id, cmd->op, cmd->cmdSize - sizeof(*cmd));
556 
557     for (size_t i = 0; i < bufSize - sizeof(*cmd); i++) {
558         printf("%.2x ", (unsigned char)cmd->buf[i]);
559     }
560     printf("\n");
561 
562     if (cmd->cmdSize < bufSize) {
563         printf("ignoring short command, cmdSize=%u, bufSize=%zu\n", cmd->cmdSize, bufSize);
564         return 0;
565     }
566 
567     if (cmd->cmdSize > bufSize) {
568         printf("command would overflow buffer, cmdSize=%u, bufSize=%zu\n", cmd->cmdSize, bufSize);
569         return -1;
570     }
571 
572     std::map<uint32_t, Context*>::iterator it;
573     it = Context::map.find((uint32_t)ctx_id);
574     if (it == Context::map.end()) {
575         printf("command submit from invalid context %d, ignoring\n", ctx_id);
576         return 0;
577     }
578 
579     Context* ctx = it->second;
580 
581     // When the context is created, the remote side should send a test command
582     // (op == 0) which we use to set up our link to this context's 'response
583     // buffer'. Only apps using EGL or GLES have this. Gralloc contexts will
584     // never hit this path because they do not submit 3D commands.
585     if (cmd->op == 0) {
586         std::map<uint32_t, Resource*>::iterator it;
587         it = Resource::map.find(*(uint32_t*)cmd->buf);
588         if (it != Resource::map.end()) {
589             Resource* res = it->second;
590             size_t cmdRespBufSize = 0U;
591             for (size_t i = 0; i < res->num_iovs; i++)
592                 cmdRespBufSize += res->iov[i].iov_len;
593             if (cmdRespBufSize == MAX_CMDRESPBUF_SIZE)
594                 ctx->cmd_resp = res;
595         }
596     }
597 
598     if (!ctx->cmd_resp) {
599         printf("context command response page not set up, ctx=%d\n", ctx_id);
600         return -1;
601     }
602 
603     VirtioGpuCmd* cmd_resp = reinterpret_cast<VirtioGpuCmd*>(ctx->cmd_resp->linear);
604 
605     // We can configure bits of the response now. The size, and any message, will
606     // be updated later. This must be done even for the dummy 'op == 0' command.
607     cmd_resp->op = cmd->op;
608     cmd_resp->cmdSize = sizeof(*cmd_resp);
609 
610     if (cmd->op == 0) {
611         // Send back a no-op response, just to keep the protocol in check
612         virgl_box box = {
613             .w = cmd_resp->cmdSize,
614             .h = 1,
615         };
616         sync_linear_to_iovec(ctx->cmd_resp, 0, &box);
617     } else {
618         // If the rcSetPuid command was already processed, this command will be
619         // processed by another thread. If not, the command data will be copied
620         // here and responded to when ctx->setFence() is called later.
621         ctx->submitCommand(buffer, bufSize);
622     }
623 
624     g_last_submit_cmd_ctx = ctx;
625     return 0;
626 }
627 
virgl_renderer_get_cap_set(uint32_t set,uint32_t * max_ver,uint32_t * max_size)628 void virgl_renderer_get_cap_set(uint32_t set, uint32_t* max_ver, uint32_t* max_size) {
629     if (!max_ver || !max_size)
630         return;
631 
632     printf("Request for caps version %u\n", set);
633 
634     switch (set) {
635         case 1:
636             *max_ver = 1;
637             *max_size = sizeof(virgl_caps_v1);
638             break;
639         case 2:
640             *max_ver = 2;
641             *max_size = sizeof(virgl_caps_v2);
642             break;
643         default:
644             *max_ver = 0;
645             *max_size = 0;
646             break;
647     }
648 }
649 
virgl_renderer_fill_caps(uint32_t set,uint32_t,void * caps_)650 void virgl_renderer_fill_caps(uint32_t set, uint32_t, void* caps_) {
651     union virgl_caps* caps = static_cast<union virgl_caps*>(caps_);
652     EGLSurface old_read_surface, old_draw_surface;
653     GLfloat range[2] = { 0.0f, 0.0f };
654     bool fill_caps_v2 = false;
655     EGLContext old_context;
656     GLint max = 0;
657 
658     if (!caps)
659         return;
660 
661     // We don't need to handle caps yet, because our guest driver's features
662     // should be as close as possible to the host driver's. But maybe some day
663     // we'll support gallium shaders and the virgl control stream, so it seems
664     // like a good idea to set up the driver caps correctly..
665 
666     // If this is broken, nothing will work properly
667     old_read_surface = s_egl.eglGetCurrentSurface(EGL_READ);
668     old_draw_surface = s_egl.eglGetCurrentSurface(EGL_DRAW);
669     old_context = s_egl.eglGetCurrentContext();
670     if (!s_egl.eglMakeCurrent(g_dpy, g_ctx0_surface, g_ctx0_surface, g_ctx0_es1)) {
671         printf("Failed to make ES1 context current\n");
672         return;
673     }
674 
675     // Don't validate 'version' because it looks like this was misdesigned
676     // upstream and won't be set; instead, 'set' was bumped from 1->2.
677 
678     switch (set) {
679         case 0:
680         case 1:
681             memset(caps, 0, sizeof(virgl_caps_v1));
682             caps->max_version = 1;
683             break;
684         case 2:
685             memset(caps, 0, sizeof(virgl_caps_v2));
686             caps->max_version = 2;
687             fill_caps_v2 = true;
688             break;
689         default:
690             caps->max_version = 0;
691             return;
692     }
693 
694     if (fill_caps_v2) {
695         printf("Will probe and fill caps version 2.\n");
696     }
697 
698     // Formats supported for textures
699 
700     caps->v1.sampler.bitmask[0] = (1 << (VIRGL_FORMAT_B8G8R8A8_UNORM - (0 * 32))) |
701                                   (1 << (VIRGL_FORMAT_B5G6R5_UNORM - (0 * 32)));
702     caps->v1.sampler.bitmask[2] = (1 << (VIRGL_FORMAT_R8G8B8A8_UNORM - (2 * 32)));
703     caps->v1.sampler.bitmask[4] = (1 << (VIRGL_FORMAT_R8G8B8X8_UNORM - (4 * 32)));
704 
705     // Formats supported for rendering
706 
707     caps->v1.render.bitmask[0] = (1 << (VIRGL_FORMAT_B8G8R8A8_UNORM - (0 * 32))) |
708                                  (1 << (VIRGL_FORMAT_B5G6R5_UNORM - (0 * 32)));
709     caps->v1.render.bitmask[2] = (1 << (VIRGL_FORMAT_R8G8B8A8_UNORM - (2 * 32)));
710     caps->v1.render.bitmask[4] = (1 << (VIRGL_FORMAT_R8G8B8X8_UNORM - (4 * 32)));
711 
712     // Could parse s_gles1.glGetString(GL_SHADING_LANGUAGE_VERSION, ...)?
713     caps->v1.glsl_level = 300;  // OpenGL ES GLSL 3.00
714 
715     // Call with any API (v1, v3) bound
716 
717     caps->v1.max_viewports = 1;
718 
719     s_gles1.glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max);
720     caps->v1.max_render_targets = max;
721 
722     s_gles1.glGetIntegerv(GL_MAX_SAMPLES_EXT, &max);
723     caps->v1.max_samples = max;
724 
725     if (fill_caps_v2) {
726         s_gles1.glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
727         caps->v2.min_aliased_point_size = range[0];
728         caps->v2.max_aliased_point_size = range[1];
729 
730         s_gles1.glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
731         caps->v2.min_aliased_line_width = range[0];
732         caps->v2.max_aliased_line_width = range[1];
733 
734         // An extension, but everybody has it
735         s_gles1.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max);
736         caps->v2.max_vertex_attribs = max;
737 
738         // Call with ES 1.0 bound *only*
739 
740         s_gles1.glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, range);
741         caps->v2.min_smooth_point_size = range[0];
742         caps->v2.max_smooth_point_size = range[1];
743 
744         s_gles1.glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range);
745         caps->v2.min_smooth_line_width = range[0];
746         caps->v2.max_smooth_line_width = range[1];
747     }
748 
749     if (!s_egl.eglMakeCurrent(g_dpy, g_ctx0_surface, g_ctx0_surface, g_ctx0_es2)) {
750         s_egl.eglMakeCurrent(g_dpy, old_draw_surface, old_read_surface, old_context);
751         printf("Failed to make ES3 context current\n");
752         return;
753     }
754 
755     // Call with ES 3.0 bound *only*
756 
757     caps->v1.bset.primitive_restart = 1;
758     caps->v1.bset.seamless_cube_map = 1;
759     caps->v1.bset.occlusion_query = 1;
760     caps->v1.bset.instanceid = 1;
761     caps->v1.bset.ubo = 1;
762 
763     s_gles1.glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &max);
764     caps->v1.max_texture_array_layers = max;
765 
766     s_gles1.glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &max);
767     caps->v1.max_uniform_blocks = max + 1;
768 
769     if (fill_caps_v2) {
770         s_gles1.glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps->v2.max_texture_lod_bias);
771 
772         s_gles1.glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &max);
773         caps->v2.max_vertex_outputs = max / 4;
774 
775         s_gles1.glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps->v2.min_texel_offset);
776         s_gles1.glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &caps->v2.max_texel_offset);
777 
778         s_gles1.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &max);
779         caps->v2.uniform_buffer_offset_alignment = max;
780     }
781 
782     // ES 2.0 extensions (fixme)
783 
784     // Gallium compatibility; not usable currently.
785     caps->v1.prim_mask = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
786 
787     if (!s_egl.eglMakeCurrent(g_dpy, old_draw_surface, old_read_surface, old_context)) {
788         printf("Failed to make no context current\n");
789     }
790 }
791 
virgl_renderer_create_fence(int client_fence_id,uint32_t cmd_type)792 int virgl_renderer_create_fence(int client_fence_id, uint32_t cmd_type) {
793     switch (cmd_type) {
794         case VIRTIO_GPU_CMD_SUBMIT_3D:
795             if (g_last_submit_cmd_ctx) {
796                 g_last_submit_cmd_ctx->setFence(client_fence_id);
797                 break;
798             }
799             [[fallthrough]];
800         default: {
801             std::lock_guard<std::mutex> lk(g_fence_deque_mutex);
802             g_fence_deque.push_back(client_fence_id);
803             break;
804         }
805     }
806     return 0;
807 }
808 
virgl_renderer_force_ctx_0(void)809 void virgl_renderer_force_ctx_0(void) {
810 #ifdef QEMU_HARDWARE_GL_INTEROP
811     if (!g_ctx0_alt)
812         return;
813 
814     if (g_cb->make_current(g_cookie, 0, g_ctx0_alt)) {
815         printf("Failed to make hardware GL context 0 current\n");
816         g_cb->destroy_gl_context(g_cookie, g_ctx0_alt);
817         g_ctx0_alt = nullptr;
818     }
819 #endif
820 }
821 
virgl_renderer_resource_create(virgl_renderer_resource_create_args * args,iovec * iov,uint32_t num_iovs)822 int virgl_renderer_resource_create(virgl_renderer_resource_create_args* args, iovec* iov,
823                                    uint32_t num_iovs) {
824     if (!args)
825         return EINVAL;
826 
827     if (args->bind == VIRGL_RES_BIND_CURSOR) {
828         // Enforce limitation of current virtio-gpu-3d implementation
829         if (args->width != 64 || args->height != 64 || args->format != VIRGL_FORMAT_B8G8R8A8_UNORM)
830             return EINVAL;
831     }
832 
833     assert(!Resource::map.count(args->handle) && "Can't insert same resource twice!");
834 
835     Resource* res = new (std::nothrow) Resource(args, num_iovs, iov);
836     if (!res)
837         return ENOMEM;
838 
839     printf("Creating Resource %u (num_iovs=%u)\n", args->handle, num_iovs);
840     return 0;
841 }
842 
virgl_renderer_resource_unref(uint32_t res_handle)843 void virgl_renderer_resource_unref(uint32_t res_handle) {
844     std::map<uint32_t, Resource*>::iterator it;
845 
846     it = Resource::map.find(res_handle);
847     if (it == Resource::map.end())
848         return;
849 
850     Resource* res = it->second;
851 
852     for (auto const& it : Context::map) {
853         Context const* ctx = it.second;
854 
855         virgl_renderer_ctx_detach_resource(ctx->handle, res->args.handle);
856     }
857 
858     assert(res->context_map.empty() && "Deleted resource was associated with contexts");
859 
860     printf("Deleting Resource %u\n", res_handle);
861     delete res;
862 }
863 
virgl_renderer_resource_attach_iov(int res_handle,iovec * iov,int num_iovs)864 int virgl_renderer_resource_attach_iov(int res_handle, iovec* iov, int num_iovs) {
865     std::map<uint32_t, Resource*>::iterator it;
866 
867     it = Resource::map.find((uint32_t)res_handle);
868     if (it == Resource::map.end())
869         return ENOENT;
870 
871     Resource* res = it->second;
872 
873     if (!res->iov) {
874         printf(
875             "Attaching backing store for Resource %d "
876             "(num_iovs=%d)\n",
877             res_handle, num_iovs);
878 
879         res->num_iovs = num_iovs;
880         res->iov = iov;
881 
882         res->reallocLinear();
883 
884         // Assumes that when resources are attached, they contain junk, and we
885         // don't need to synchronize with the linear buffer
886     }
887 
888     return 0;
889 }
890 
virgl_renderer_resource_detach_iov(int res_handle,iovec ** iov,int * num_iovs)891 void virgl_renderer_resource_detach_iov(int res_handle, iovec** iov, int* num_iovs) {
892     std::map<uint32_t, Resource*>::iterator it;
893 
894     it = Resource::map.find((uint32_t)res_handle);
895     if (it == Resource::map.end())
896         return;
897 
898     Resource* res = it->second;
899 
900     printf("Detaching backing store for Resource %d\n", res_handle);
901 
902     // Synchronize our linear buffer, if any, with the iovec that we are about
903     // to give up. Most likely this is not required, but it seems cleaner.
904     virgl_box box = {
905         .w = res->args.width,
906         .h = res->args.height,
907     };
908     sync_linear_to_iovec(res, 0, &box);
909 
910     if (num_iovs)
911         *num_iovs = res->num_iovs;
912     res->num_iovs = 0U;
913 
914     if (iov)
915         *iov = res->iov;
916     res->iov = nullptr;
917 
918     res->reallocLinear();
919 }
920 
virgl_renderer_resource_get_info(int res_handle,virgl_renderer_resource_info * info)921 int virgl_renderer_resource_get_info(int res_handle, virgl_renderer_resource_info* info) {
922     if (!info)
923         return EINVAL;
924 
925     std::map<uint32_t, Resource*>::iterator it;
926 
927     it = Resource::map.find((uint32_t)res_handle);
928     if (it == Resource::map.end())
929         return ENOENT;
930 
931     Resource* res = it->second;
932 
933     uint32_t bpp = 4U;
934     switch (res->args.format) {
935         case VIRGL_FORMAT_B8G8R8A8_UNORM:
936             info->drm_fourcc = DRM_FORMAT_BGRA8888;
937             break;
938         case VIRGL_FORMAT_B5G6R5_UNORM:
939             info->drm_fourcc = DRM_FORMAT_BGR565;
940             bpp = 2U;
941             break;
942         case VIRGL_FORMAT_R8G8B8A8_UNORM:
943             info->drm_fourcc = DRM_FORMAT_RGBA8888;
944             break;
945         case VIRGL_FORMAT_R8G8B8X8_UNORM:
946             info->drm_fourcc = DRM_FORMAT_RGBX8888;
947             break;
948         default:
949             return EINVAL;
950     }
951 
952 #ifdef QEMU_HARDWARE_GL_INTEROP
953     GLenum type = GL_UNSIGNED_BYTE;
954     GLenum format = GL_RGBA;
955     switch (res->args.format) {
956         case VIRGL_FORMAT_B8G8R8A8_UNORM:
957             format = 0x80E1;  // GL_BGRA
958             break;
959         case VIRGL_FORMAT_B5G6R5_UNORM:
960             type = GL_UNSIGNED_SHORT_5_6_5;
961             format = GL_RGB;
962             break;
963         case VIRGL_FORMAT_R8G8B8X8_UNORM:
964             format = GL_RGB;
965             break;
966     }
967 
968     if (!res->tex_id) {
969         g_glGenTextures(1, &res->tex_id);
970         g_glBindTexture(GL_TEXTURE_2D, res->tex_id);
971         g_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
972         g_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
973         g_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
974         g_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
975     } else {
976         g_glBindTexture(GL_TEXTURE_2D, res->tex_id);
977     }
978 
979     g_glPixelStorei(GL_UNPACK_ROW_LENGTH, ALIGN(res->args.width, 16));
980     g_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, res->args.width, res->args.height, 0, format, type,
981                    res->linear);
982 #endif
983 
984     info->stride = ALIGN(res->args.width * bpp, 16U);
985     info->virgl_format = res->args.format;
986     info->handle = res->args.handle;
987     info->height = res->args.height;
988     info->width = res->args.width;
989     info->depth = res->args.depth;
990     info->flags = res->args.flags;
991     info->tex_id = res->tex_id;
992 
993     printf("Scanning out Resource %d\n", res_handle);
994     dump_global_state();
995 
996     return 0;
997 }
998 
virgl_renderer_context_create(uint32_t handle,uint32_t nlen,const char * name)999 int virgl_renderer_context_create(uint32_t handle, uint32_t nlen, const char* name) {
1000     assert(!Context::map.count(handle) && "Can't insert same context twice!");
1001 
1002     Context* ctx = new (std::nothrow) Context(handle, name, nlen, process_cmd, g_dpy);
1003     if (!ctx)
1004         return ENOMEM;
1005 
1006     printf("Creating Context %u (%.*s)\n", handle, (int)nlen, name);
1007     return 0;
1008 }
1009 
virgl_renderer_context_destroy(uint32_t handle)1010 void virgl_renderer_context_destroy(uint32_t handle) {
1011     std::map<uint32_t, Context*>::iterator it;
1012     it = Context::map.find(handle);
1013     if (it == Context::map.end())
1014         return;
1015 
1016     Context* ctx = it->second;
1017     printf("Destroying Context %u\n", handle);
1018     delete ctx;
1019 }
1020 
virgl_renderer_transfer_read_iov(uint32_t handle,uint32_t,uint32_t,uint32_t,uint32_t,virgl_box * box,uint64_t offset,iovec *,int)1021 int virgl_renderer_transfer_read_iov(uint32_t handle, uint32_t, uint32_t, uint32_t, uint32_t,
1022                                      virgl_box* box, uint64_t offset, iovec*, int) {
1023     // stride, layer_stride and level are not set by minigbm, so don't try to
1024     // validate them right now. iov and iovec_cnt are always passed as nullptr
1025     // and 0 by qemu, so ignore those too
1026 
1027     std::map<uint32_t, Resource*>::iterator it;
1028     it = Resource::map.find((uint32_t)handle);
1029     if (it == Resource::map.end())
1030         return EINVAL;
1031 
1032     return sync_linear_to_iovec(it->second, offset, box);
1033 }
1034 
virgl_renderer_transfer_write_iov(uint32_t handle,uint32_t,int,uint32_t,uint32_t,virgl_box * box,uint64_t offset,iovec *,unsigned int)1035 int virgl_renderer_transfer_write_iov(uint32_t handle, uint32_t, int, uint32_t, uint32_t,
1036                                       virgl_box* box, uint64_t offset, iovec*, unsigned int) {
1037     // stride, layer_stride and level are not set by minigbm, so don't try to
1038     // validate them right now. iov and iovec_cnt are always passed as nullptr
1039     // and 0 by qemu, so ignore those too
1040 
1041     std::map<uint32_t, Resource*>::iterator it;
1042     it = Resource::map.find((uint32_t)handle);
1043     if (it == Resource::map.end())
1044         return EINVAL;
1045 
1046     return sync_iovec_to_linear(it->second, offset, box);
1047 }
1048 
virgl_renderer_ctx_attach_resource(int ctx_id,int res_handle)1049 void virgl_renderer_ctx_attach_resource(int ctx_id, int res_handle) {
1050     std::map<uint32_t, Context*>::iterator ctx_it;
1051 
1052     ctx_it = Context::map.find((uint32_t)ctx_id);
1053     if (ctx_it == Context::map.end())
1054         return;
1055 
1056     Context* ctx = ctx_it->second;
1057 
1058     assert(!ctx->resource_map.count((uint32_t)res_handle) &&
1059            "Can't attach resource to context twice!");
1060 
1061     std::map<uint32_t, Resource*>::iterator res_it;
1062 
1063     res_it = Resource::map.find((uint32_t)res_handle);
1064     if (res_it == Resource::map.end())
1065         return;
1066 
1067     Resource* res = res_it->second;
1068 
1069     printf("Attaching Resource %d to Context %d\n", res_handle, ctx_id);
1070     res->context_map.emplace((uint32_t)ctx_id, ctx);
1071     ctx->resource_map.emplace((uint32_t)res_handle, res);
1072 }
1073 
virgl_renderer_ctx_detach_resource(int ctx_id,int res_handle)1074 void virgl_renderer_ctx_detach_resource(int ctx_id, int res_handle) {
1075     std::map<uint32_t, Context*>::iterator ctx_it;
1076 
1077     ctx_it = Context::map.find((uint32_t)ctx_id);
1078     if (ctx_it == Context::map.end())
1079         return;
1080 
1081     Context* ctx = ctx_it->second;
1082 
1083     std::map<uint32_t, Resource*>::iterator res_it;
1084 
1085     res_it = ctx->resource_map.find((uint32_t)res_handle);
1086     if (res_it == ctx->resource_map.end())
1087         return;
1088 
1089     Resource* res = res_it->second;
1090 
1091     ctx_it = res->context_map.find((uint32_t)ctx_id);
1092     if (ctx_it == res->context_map.end())
1093         return;
1094 
1095     printf("Detaching Resource %d from Context %d\n", res_handle, ctx_id);
1096     if (ctx->cmd_resp && ctx->cmd_resp->args.handle == (uint32_t)res_handle)
1097         ctx->cmd_resp = nullptr;
1098     ctx->resource_map.erase(res_it);
1099     res->context_map.erase(ctx_it);
1100 }
1101