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