Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/winsys/svga/drm/vmw_screen_svga.c
4573 views
1
/**********************************************************
2
* Copyright 2009-2015 VMware, Inc. All rights reserved.
3
*
4
* Permission is hereby granted, free of charge, to any person
5
* obtaining a copy of this software and associated documentation
6
* files (the "Software"), to deal in the Software without
7
* restriction, including without limitation the rights to use, copy,
8
* modify, merge, publish, distribute, sublicense, and/or sell copies
9
* of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice shall be
13
* included in all copies or substantial portions of the Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* SOFTWARE.
23
*
24
**********************************************************/
25
26
/**
27
* @file
28
* This file implements the SVGA interface into this winsys, defined
29
* in drivers/svga/svga_winsys.h.
30
*
31
* @author Keith Whitwell
32
* @author Jose Fonseca
33
*/
34
35
#include <libsync.h>
36
37
#include "svga_cmd.h"
38
#include "svga3d_caps.h"
39
40
#include "util/os_file.h"
41
#include "util/u_inlines.h"
42
#include "util/u_math.h"
43
#include "util/u_memory.h"
44
#include "pipebuffer/pb_buffer.h"
45
#include "pipebuffer/pb_bufmgr.h"
46
#include "svga_winsys.h"
47
#include "vmw_context.h"
48
#include "vmw_screen.h"
49
#include "vmw_surface.h"
50
#include "vmw_buffer.h"
51
#include "vmw_fence.h"
52
#include "vmw_msg.h"
53
#include "vmw_shader.h"
54
#include "vmw_query.h"
55
#include "svga3d_surfacedefs.h"
56
57
/**
58
* Try to get a surface backing buffer from the cache
59
* if it's this size or smaller.
60
*/
61
#define VMW_TRY_CACHED_SIZE (2*1024*1024)
62
63
static struct svga_winsys_buffer *
64
vmw_svga_winsys_buffer_create(struct svga_winsys_screen *sws,
65
unsigned alignment,
66
unsigned usage,
67
unsigned size)
68
{
69
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
70
struct vmw_buffer_desc desc;
71
struct pb_manager *provider;
72
struct pb_buffer *buffer;
73
74
memset(&desc, 0, sizeof desc);
75
desc.pb_desc.alignment = alignment;
76
desc.pb_desc.usage = usage;
77
78
if (usage == SVGA_BUFFER_USAGE_PINNED) {
79
if (vws->pools.query_fenced == NULL && !vmw_query_pools_init(vws))
80
return NULL;
81
provider = vws->pools.query_fenced;
82
} else if (usage == SVGA_BUFFER_USAGE_SHADER) {
83
provider = vws->pools.mob_shader_slab_fenced;
84
} else {
85
if (size > VMW_GMR_POOL_SIZE)
86
return NULL;
87
provider = vws->pools.gmr_fenced;
88
}
89
90
assert(provider);
91
buffer = provider->create_buffer(provider, size, &desc.pb_desc);
92
93
if(!buffer && provider == vws->pools.gmr_fenced) {
94
95
assert(provider);
96
provider = vws->pools.gmr_slab_fenced;
97
buffer = provider->create_buffer(provider, size, &desc.pb_desc);
98
}
99
100
if (!buffer)
101
return NULL;
102
103
return vmw_svga_winsys_buffer_wrap(buffer);
104
}
105
106
107
static void
108
vmw_svga_winsys_fence_reference(struct svga_winsys_screen *sws,
109
struct pipe_fence_handle **pdst,
110
struct pipe_fence_handle *src)
111
{
112
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
113
114
vmw_fence_reference(vws, pdst, src);
115
}
116
117
118
static int
119
vmw_svga_winsys_fence_signalled(struct svga_winsys_screen *sws,
120
struct pipe_fence_handle *fence,
121
unsigned flag)
122
{
123
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
124
125
return vmw_fence_signalled(vws, fence, flag);
126
}
127
128
129
static int
130
vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws,
131
struct pipe_fence_handle *fence,
132
uint64_t timeout,
133
unsigned flag)
134
{
135
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
136
137
return vmw_fence_finish(vws, fence, timeout, flag);
138
}
139
140
141
static int
142
vmw_svga_winsys_fence_get_fd(struct svga_winsys_screen *sws,
143
struct pipe_fence_handle *fence,
144
boolean duplicate)
145
{
146
if (duplicate)
147
return os_dupfd_cloexec(vmw_fence_get_fd(fence));
148
else
149
return vmw_fence_get_fd(fence);
150
}
151
152
153
static void
154
vmw_svga_winsys_fence_create_fd(struct svga_winsys_screen *sws,
155
struct pipe_fence_handle **fence,
156
int32_t fd)
157
{
158
*fence = vmw_fence_create(NULL, 0, 0, 0, os_dupfd_cloexec(fd));
159
}
160
161
static int
162
vmw_svga_winsys_fence_server_sync(struct svga_winsys_screen *sws,
163
int32_t *context_fd,
164
struct pipe_fence_handle *fence)
165
{
166
int32_t fd = sws->fence_get_fd(sws, fence, FALSE);
167
168
/* If we don't have fd, we don't need to merge fd into the context's fd. */
169
if (fd == -1)
170
return 0;
171
172
return sync_accumulate("vmwgfx", context_fd, fd);
173
}
174
175
176
static struct svga_winsys_surface *
177
vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
178
SVGA3dSurfaceAllFlags flags,
179
SVGA3dSurfaceFormat format,
180
unsigned usage,
181
SVGA3dSize size,
182
uint32 numLayers,
183
uint32 numMipLevels,
184
unsigned sampleCount)
185
{
186
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
187
struct vmw_svga_winsys_surface *surface;
188
struct vmw_buffer_desc desc;
189
struct pb_manager *provider;
190
uint32_t buffer_size;
191
uint32_t num_samples = 1;
192
SVGA3dMSPattern multisample_pattern = SVGA3D_MS_PATTERN_NONE;
193
SVGA3dMSQualityLevel quality_level = SVGA3D_MS_QUALITY_NONE;
194
195
memset(&desc, 0, sizeof(desc));
196
surface = CALLOC_STRUCT(vmw_svga_winsys_surface);
197
if(!surface)
198
goto no_surface;
199
200
pipe_reference_init(&surface->refcnt, 1);
201
p_atomic_set(&surface->validated, 0);
202
surface->screen = vws;
203
(void) mtx_init(&surface->mutex, mtx_plain);
204
surface->shared = !!(usage & SVGA_SURFACE_USAGE_SHARED);
205
provider = (surface->shared) ? vws->pools.gmr : vws->pools.mob_fenced;
206
207
/*
208
* When multisampling is not supported sample count received is 0,
209
* otherwise should have a valid sample count.
210
*/
211
if ((flags & SVGA3D_SURFACE_MULTISAMPLE) != 0) {
212
if (sampleCount == 0)
213
goto no_sid;
214
num_samples = sampleCount;
215
multisample_pattern = SVGA3D_MS_PATTERN_STANDARD;
216
quality_level = SVGA3D_MS_QUALITY_FULL;
217
}
218
219
/*
220
* Used for the backing buffer GB surfaces, and to approximate
221
* when to flush on non-GB hosts.
222
*/
223
buffer_size = svga3dsurface_get_serialized_size_extended(format, size,
224
numMipLevels,
225
numLayers,
226
num_samples);
227
if (flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
228
buffer_size += sizeof(SVGA3dDXSOState);
229
230
if (buffer_size > vws->ioctl.max_texture_size) {
231
goto no_sid;
232
}
233
234
if (sws->have_gb_objects) {
235
SVGAGuestPtr ptr = {0,0};
236
237
/*
238
* If the backing buffer size is small enough, try to allocate a
239
* buffer out of the buffer cache. Otherwise, let the kernel allocate
240
* a suitable buffer for us.
241
*/
242
if (buffer_size < VMW_TRY_CACHED_SIZE && !surface->shared) {
243
struct pb_buffer *pb_buf;
244
245
surface->size = buffer_size;
246
desc.pb_desc.alignment = 4096;
247
desc.pb_desc.usage = 0;
248
pb_buf = provider->create_buffer(provider, buffer_size, &desc.pb_desc);
249
surface->buf = vmw_svga_winsys_buffer_wrap(pb_buf);
250
if (surface->buf && !vmw_gmr_bufmgr_region_ptr(pb_buf, &ptr))
251
assert(0);
252
}
253
254
surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage,
255
size, numLayers,
256
numMipLevels, sampleCount,
257
ptr.gmrId,
258
multisample_pattern,
259
quality_level,
260
surface->buf ? NULL :
261
&desc.region);
262
263
if (surface->sid == SVGA3D_INVALID_ID) {
264
if (surface->buf == NULL) {
265
goto no_sid;
266
} else {
267
/*
268
* Kernel refused to allocate a surface for us.
269
* Perhaps something was wrong with our buffer?
270
* This is really a guard against future new size requirements
271
* on the backing buffers.
272
*/
273
vmw_svga_winsys_buffer_destroy(sws, surface->buf);
274
surface->buf = NULL;
275
surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage,
276
size, numLayers,
277
numMipLevels, sampleCount,
278
0, multisample_pattern,
279
quality_level,
280
&desc.region);
281
if (surface->sid == SVGA3D_INVALID_ID)
282
goto no_sid;
283
}
284
}
285
286
/*
287
* If the kernel created the buffer for us, wrap it into a
288
* vmw_svga_winsys_buffer.
289
*/
290
if (surface->buf == NULL) {
291
struct pb_buffer *pb_buf;
292
293
surface->size = vmw_region_size(desc.region);
294
desc.pb_desc.alignment = 4096;
295
desc.pb_desc.usage = VMW_BUFFER_USAGE_SHARED;
296
pb_buf = provider->create_buffer(provider, surface->size,
297
&desc.pb_desc);
298
surface->buf = vmw_svga_winsys_buffer_wrap(pb_buf);
299
if (surface->buf == NULL) {
300
vmw_ioctl_region_destroy(desc.region);
301
vmw_ioctl_surface_destroy(vws, surface->sid);
302
goto no_sid;
303
}
304
}
305
} else {
306
/* Legacy surface only support 32-bit svga3d flags */
307
surface->sid = vmw_ioctl_surface_create(vws, (SVGA3dSurface1Flags)flags,
308
format, usage, size, numLayers,
309
numMipLevels, sampleCount);
310
if(surface->sid == SVGA3D_INVALID_ID)
311
goto no_sid;
312
313
/* Best estimate for surface size, used for early flushing. */
314
surface->size = buffer_size;
315
surface->buf = NULL;
316
}
317
318
return svga_winsys_surface(surface);
319
320
no_sid:
321
if (surface->buf)
322
vmw_svga_winsys_buffer_destroy(sws, surface->buf);
323
324
FREE(surface);
325
no_surface:
326
return NULL;
327
}
328
329
static boolean
330
vmw_svga_winsys_surface_can_create(struct svga_winsys_screen *sws,
331
SVGA3dSurfaceFormat format,
332
SVGA3dSize size,
333
uint32 numLayers,
334
uint32 numMipLevels,
335
uint32 numSamples)
336
{
337
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
338
uint32_t buffer_size;
339
340
buffer_size = svga3dsurface_get_serialized_size(format, size,
341
numMipLevels,
342
numLayers);
343
if (numSamples > 1)
344
buffer_size *= numSamples;
345
346
if (buffer_size > vws->ioctl.max_texture_size) {
347
return FALSE;
348
}
349
return TRUE;
350
}
351
352
353
static boolean
354
vmw_svga_winsys_surface_is_flushed(struct svga_winsys_screen *sws,
355
struct svga_winsys_surface *surface)
356
{
357
struct vmw_svga_winsys_surface *vsurf = vmw_svga_winsys_surface(surface);
358
return (p_atomic_read(&vsurf->validated) == 0);
359
}
360
361
362
static void
363
vmw_svga_winsys_surface_ref(struct svga_winsys_screen *sws,
364
struct svga_winsys_surface **pDst,
365
struct svga_winsys_surface *src)
366
{
367
struct vmw_svga_winsys_surface *d_vsurf = vmw_svga_winsys_surface(*pDst);
368
struct vmw_svga_winsys_surface *s_vsurf = vmw_svga_winsys_surface(src);
369
370
vmw_svga_winsys_surface_reference(&d_vsurf, s_vsurf);
371
*pDst = svga_winsys_surface(d_vsurf);
372
}
373
374
375
static void
376
vmw_svga_winsys_destroy(struct svga_winsys_screen *sws)
377
{
378
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
379
380
vmw_winsys_destroy(vws);
381
}
382
383
384
static SVGA3dHardwareVersion
385
vmw_svga_winsys_get_hw_version(struct svga_winsys_screen *sws)
386
{
387
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
388
389
if (sws->have_gb_objects)
390
return SVGA3D_HWVERSION_WS8_B1;
391
392
return (SVGA3dHardwareVersion) vws->ioctl.hwversion;
393
}
394
395
396
static boolean
397
vmw_svga_winsys_get_cap(struct svga_winsys_screen *sws,
398
SVGA3dDevCapIndex index,
399
SVGA3dDevCapResult *result)
400
{
401
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
402
403
if (index > vws->ioctl.num_cap_3d ||
404
index >= SVGA3D_DEVCAP_MAX ||
405
!vws->ioctl.cap_3d[index].has_cap)
406
return FALSE;
407
408
*result = vws->ioctl.cap_3d[index].result;
409
return TRUE;
410
}
411
412
struct svga_winsys_gb_shader *
413
vmw_svga_winsys_shader_create(struct svga_winsys_screen *sws,
414
SVGA3dShaderType type,
415
const uint32 *bytecode,
416
uint32 bytecodeLen)
417
{
418
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
419
struct vmw_svga_winsys_shader *shader;
420
void *code;
421
422
shader = CALLOC_STRUCT(vmw_svga_winsys_shader);
423
if(!shader)
424
goto out_no_shader;
425
426
pipe_reference_init(&shader->refcnt, 1);
427
p_atomic_set(&shader->validated, 0);
428
shader->screen = vws;
429
shader->buf = vmw_svga_winsys_buffer_create(sws, 64,
430
SVGA_BUFFER_USAGE_SHADER,
431
bytecodeLen);
432
if (!shader->buf)
433
goto out_no_buf;
434
435
code = vmw_svga_winsys_buffer_map(sws, shader->buf, PIPE_MAP_WRITE);
436
if (!code)
437
goto out_no_buf;
438
439
memcpy(code, bytecode, bytecodeLen);
440
vmw_svga_winsys_buffer_unmap(sws, shader->buf);
441
442
if (!sws->have_vgpu10) {
443
shader->shid = vmw_ioctl_shader_create(vws, type, bytecodeLen);
444
if (shader->shid == SVGA3D_INVALID_ID)
445
goto out_no_shid;
446
}
447
448
return svga_winsys_shader(shader);
449
450
out_no_shid:
451
vmw_svga_winsys_buffer_destroy(sws, shader->buf);
452
out_no_buf:
453
FREE(shader);
454
out_no_shader:
455
return NULL;
456
}
457
458
void
459
vmw_svga_winsys_shader_destroy(struct svga_winsys_screen *sws,
460
struct svga_winsys_gb_shader *shader)
461
{
462
struct vmw_svga_winsys_shader *d_shader =
463
vmw_svga_winsys_shader(shader);
464
465
vmw_svga_winsys_shader_reference(&d_shader, NULL);
466
}
467
468
static void
469
vmw_svga_winsys_stats_inc(enum svga_stats_count index)
470
{
471
}
472
473
static void
474
vmw_svga_winsys_stats_time_push(enum svga_stats_time index,
475
struct svga_winsys_stats_timeframe *tf)
476
{
477
}
478
479
static void
480
vmw_svga_winsys_stats_time_pop()
481
{
482
}
483
484
boolean
485
vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws)
486
{
487
vws->base.destroy = vmw_svga_winsys_destroy;
488
vws->base.get_hw_version = vmw_svga_winsys_get_hw_version;
489
vws->base.get_cap = vmw_svga_winsys_get_cap;
490
vws->base.context_create = vmw_svga_winsys_context_create;
491
vws->base.surface_create = vmw_svga_winsys_surface_create;
492
vws->base.surface_is_flushed = vmw_svga_winsys_surface_is_flushed;
493
vws->base.surface_reference = vmw_svga_winsys_surface_ref;
494
vws->base.surface_can_create = vmw_svga_winsys_surface_can_create;
495
vws->base.buffer_create = vmw_svga_winsys_buffer_create;
496
vws->base.buffer_map = vmw_svga_winsys_buffer_map;
497
vws->base.buffer_unmap = vmw_svga_winsys_buffer_unmap;
498
vws->base.buffer_destroy = vmw_svga_winsys_buffer_destroy;
499
vws->base.surface_init = vmw_svga_winsys_surface_init;
500
vws->base.fence_reference = vmw_svga_winsys_fence_reference;
501
vws->base.fence_signalled = vmw_svga_winsys_fence_signalled;
502
vws->base.shader_create = vmw_svga_winsys_shader_create;
503
vws->base.shader_destroy = vmw_svga_winsys_shader_destroy;
504
vws->base.fence_finish = vmw_svga_winsys_fence_finish;
505
vws->base.fence_get_fd = vmw_svga_winsys_fence_get_fd;
506
vws->base.fence_create_fd = vmw_svga_winsys_fence_create_fd;
507
vws->base.fence_server_sync = vmw_svga_winsys_fence_server_sync;
508
509
vws->base.query_create = vmw_svga_winsys_query_create;
510
vws->base.query_init = vmw_svga_winsys_query_init;
511
vws->base.query_destroy = vmw_svga_winsys_query_destroy;
512
vws->base.query_get_result = vmw_svga_winsys_query_get_result;
513
514
vws->base.stats_inc = vmw_svga_winsys_stats_inc;
515
vws->base.stats_time_push = vmw_svga_winsys_stats_time_push;
516
vws->base.stats_time_pop = vmw_svga_winsys_stats_time_pop;
517
518
vws->base.host_log = vmw_svga_winsys_host_log;
519
520
return TRUE;
521
}
522
523
524
525