1 /**************************************************************************
2 *
3 * Copyright 2009, VMware, Inc.
4 * All Rights Reserved.
5 * Copyright 2010 George Sapountzis <[email protected]>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include "mesa_interface.h"
30 #include "git_sha1.h"
31 #include "util/format/u_format.h"
32 #include "util/u_memory.h"
33 #include "util/u_inlines.h"
34 #include "util/box.h"
35 #include "pipe/p_context.h"
36 #include "pipe-loader/pipe_loader.h"
37 #include "frontend/drisw_api.h"
38 #include "state_tracker/st_context.h"
39
40 #include "dri_screen.h"
41 #include "dri_context.h"
42 #include "dri_drawable.h"
43 #include "dri_helpers.h"
44 #include "dri_query_renderer.h"
45
46 #include "util/libsync.h"
47
48 #ifdef HAVE_LIBDRM
49 #include <xf86drm.h>
50 #endif
51
52 DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", false);
53
54 static inline void
get_drawable_info(struct dri_drawable * drawable,int * x,int * y,int * w,int * h)55 get_drawable_info(struct dri_drawable *drawable, int *x, int *y, int *w, int *h)
56 {
57 const __DRIswrastLoaderExtension *loader = drawable->screen->swrast_loader;
58
59 loader->getDrawableInfo(opaque_dri_drawable(drawable),
60 x, y, w, h,
61 drawable->loaderPrivate);
62 }
63
64 static inline void
put_image(struct dri_drawable * drawable,void * data,unsigned width,unsigned height)65 put_image(struct dri_drawable *drawable, void *data, unsigned width, unsigned height)
66 {
67 const __DRIswrastLoaderExtension *loader = drawable->screen->swrast_loader;
68
69 loader->putImage(opaque_dri_drawable(drawable), __DRI_SWRAST_IMAGE_OP_SWAP,
70 0, 0, width, height,
71 data, drawable->loaderPrivate);
72 }
73
74 static inline void
put_image2(struct dri_drawable * drawable,void * data,int x,int y,unsigned width,unsigned height,unsigned stride)75 put_image2(struct dri_drawable *drawable, void *data, int x, int y,
76 unsigned width, unsigned height, unsigned stride)
77 {
78 const __DRIswrastLoaderExtension *loader = drawable->screen->swrast_loader;
79
80 loader->putImage2(opaque_dri_drawable(drawable), __DRI_SWRAST_IMAGE_OP_SWAP,
81 x, y, width, height, stride,
82 data, drawable->loaderPrivate);
83 }
84
85 static inline void
put_image_shm(struct dri_drawable * drawable,int shmid,char * shmaddr,unsigned offset,unsigned offset_x,int x,int y,unsigned width,unsigned height,unsigned stride)86 put_image_shm(struct dri_drawable *drawable, int shmid, char *shmaddr,
87 unsigned offset, unsigned offset_x, int x, int y,
88 unsigned width, unsigned height, unsigned stride)
89 {
90 const __DRIswrastLoaderExtension *loader = drawable->screen->swrast_loader;
91
92 /* if we have the newer interface, don't have to add the offset_x here. */
93 if (loader->base.version > 4 && loader->putImageShm2)
94 loader->putImageShm2(opaque_dri_drawable(drawable), __DRI_SWRAST_IMAGE_OP_SWAP,
95 x, y, width, height, stride,
96 shmid, shmaddr, offset, drawable->loaderPrivate);
97 else
98 loader->putImageShm(opaque_dri_drawable(drawable), __DRI_SWRAST_IMAGE_OP_SWAP,
99 x, y, width, height, stride,
100 shmid, shmaddr, offset + offset_x, drawable->loaderPrivate);
101 }
102
103 static inline void
get_image(struct dri_drawable * drawable,int x,int y,int width,int height,void * data)104 get_image(struct dri_drawable *drawable, int x, int y, int width, int height, void *data)
105 {
106 const __DRIswrastLoaderExtension *loader = drawable->screen->swrast_loader;
107
108 loader->getImage(opaque_dri_drawable(drawable),
109 x, y, width, height,
110 data, drawable->loaderPrivate);
111 }
112
113 static inline void
get_image2(struct dri_drawable * drawable,int x,int y,int width,int height,int stride,void * data)114 get_image2(struct dri_drawable *drawable, int x, int y, int width, int height, int stride, void *data)
115 {
116 const __DRIswrastLoaderExtension *loader = drawable->screen->swrast_loader;
117
118 /* getImage2 support is only in version 3 or newer */
119 if (loader->base.version < 3)
120 return;
121
122 loader->getImage2(opaque_dri_drawable(drawable),
123 x, y, width, height, stride,
124 data, drawable->loaderPrivate);
125 }
126
127 static inline bool
get_image_shm(struct dri_drawable * drawable,int x,int y,int width,int height,struct pipe_resource * res)128 get_image_shm(struct dri_drawable *drawable, int x, int y, int width, int height,
129 struct pipe_resource *res)
130 {
131 const __DRIswrastLoaderExtension *loader = drawable->screen->swrast_loader;
132 struct winsys_handle whandle;
133
134 whandle.type = WINSYS_HANDLE_TYPE_SHMID;
135
136 if (loader->base.version < 4 || !loader->getImageShm)
137 return false;
138
139 if (!res->screen->resource_get_handle(res->screen, NULL, res, &whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE))
140 return false;
141
142 if (loader->base.version > 5 && loader->getImageShm2)
143 return loader->getImageShm2(opaque_dri_drawable(drawable), x, y, width, height, whandle.handle, drawable->loaderPrivate);
144
145 loader->getImageShm(opaque_dri_drawable(drawable), x, y, width, height, whandle.handle, drawable->loaderPrivate);
146 return true;
147 }
148
149 static void
drisw_update_drawable_info(struct dri_drawable * drawable)150 drisw_update_drawable_info(struct dri_drawable *drawable)
151 {
152 int x, y;
153
154 get_drawable_info(drawable, &x, &y, &drawable->w, &drawable->h);
155 }
156
157 static void
drisw_get_image(struct dri_drawable * drawable,int x,int y,unsigned width,unsigned height,unsigned stride,void * data)158 drisw_get_image(struct dri_drawable *drawable,
159 int x, int y, unsigned width, unsigned height, unsigned stride,
160 void *data)
161 {
162 int draw_x, draw_y, draw_w, draw_h;
163
164 get_drawable_info(drawable, &draw_x, &draw_y, &draw_w, &draw_h);
165 get_image2(drawable, x, y, draw_w, draw_h, stride, data);
166 }
167
168 static void
drisw_put_image(struct dri_drawable * drawable,void * data,unsigned width,unsigned height)169 drisw_put_image(struct dri_drawable *drawable,
170 void *data, unsigned width, unsigned height)
171 {
172 put_image(drawable, data, width, height);
173 }
174
175 static void
drisw_put_image2(struct dri_drawable * drawable,void * data,int x,int y,unsigned width,unsigned height,unsigned stride)176 drisw_put_image2(struct dri_drawable *drawable,
177 void *data, int x, int y, unsigned width, unsigned height,
178 unsigned stride)
179 {
180 put_image2(drawable, data, x, y, width, height, stride);
181 }
182
183 static inline void
drisw_put_image_shm(struct dri_drawable * drawable,int shmid,char * shmaddr,unsigned offset,unsigned offset_x,int x,int y,unsigned width,unsigned height,unsigned stride)184 drisw_put_image_shm(struct dri_drawable *drawable,
185 int shmid, char *shmaddr, unsigned offset,
186 unsigned offset_x,
187 int x, int y, unsigned width, unsigned height,
188 unsigned stride)
189 {
190 put_image_shm(drawable, shmid, shmaddr, offset, offset_x, x, y, width, height, stride);
191 }
192
193 static inline void
drisw_present_texture(struct pipe_context * pipe,struct dri_drawable * drawable,struct pipe_resource * ptex,unsigned nrects,struct pipe_box * sub_box)194 drisw_present_texture(struct pipe_context *pipe, struct dri_drawable *drawable,
195 struct pipe_resource *ptex, unsigned nrects, struct pipe_box *sub_box)
196 {
197 struct dri_screen *screen = drawable->screen;
198
199 if (screen->swrast_no_present)
200 return;
201
202 screen->base.screen->flush_frontbuffer(screen->base.screen, pipe, ptex, 0, 0, drawable, nrects, sub_box);
203 }
204
205 static inline void
drisw_invalidate_drawable(struct dri_drawable * drawable)206 drisw_invalidate_drawable(struct dri_drawable *drawable)
207 {
208 drawable->texture_stamp = drawable->lastStamp - 1;
209
210 p_atomic_inc(&drawable->base.stamp);
211 }
212
213 static inline void
drisw_copy_to_front(struct pipe_context * pipe,struct dri_drawable * drawable,struct pipe_resource * ptex,int nboxes,struct pipe_box * boxes)214 drisw_copy_to_front(struct pipe_context *pipe,
215 struct dri_drawable *drawable,
216 struct pipe_resource *ptex,
217 int nboxes, struct pipe_box *boxes)
218 {
219 drisw_present_texture(pipe, drawable, ptex, nboxes, boxes);
220
221 drisw_invalidate_drawable(drawable);
222 }
223
224 /*
225 * Backend functions for pipe_frontend_drawable and swap_buffers.
226 */
227
228 static void
drisw_swap_buffers_with_damage(struct dri_drawable * drawable,int nrects,const int * rects)229 drisw_swap_buffers_with_damage(struct dri_drawable *drawable, int nrects, const int *rects)
230 {
231 struct dri_context *ctx = dri_get_current();
232 struct dri_screen *screen = drawable->screen;
233 struct pipe_resource *ptex;
234
235 if (!ctx)
236 return;
237
238 /* Wait for glthread to finish because we can't use pipe_context from
239 * multiple threads.
240 */
241 _mesa_glthread_finish(ctx->st->ctx);
242
243 ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
244
245 if (ptex) {
246 struct pipe_fence_handle *fence = NULL;
247
248 struct pipe_box stack_boxes[64];
249 if (nrects > ARRAY_SIZE(stack_boxes))
250 nrects = 0;
251 if (nrects) {
252 for (unsigned int i = 0; i < nrects; i++) {
253 const int *rect = &rects[i * 4];
254
255 int w = MIN2(rect[2], ptex->width0);
256 int h = MIN2(rect[3], ptex->height0);
257 int x = CLAMP(rect[0], 0, ptex->width0);
258 int y = CLAMP(ptex->height0 - rect[1] - h, 0, ptex->height0);
259
260 if (h > ptex->height0 - y)
261 h = ptex->height0 - y;
262
263 u_box_2d(x, y, w, h, &stack_boxes[i]);
264 }
265 }
266
267 if (ctx->pp)
268 pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
269
270 if (ctx->hud)
271 hud_run(ctx->hud, ctx->st->cso_context, ptex);
272
273 st_context_flush(ctx->st, ST_FLUSH_FRONT, &fence, NULL, NULL);
274
275 if (drawable->stvis.samples > 1) {
276 /* Resolve the back buffer. */
277 dri_pipe_blit(ctx->st->pipe,
278 drawable->textures[ST_ATTACHMENT_BACK_LEFT],
279 drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]);
280 }
281
282 screen->base.screen->fence_finish(screen->base.screen, ctx->st->pipe,
283 fence, OS_TIMEOUT_INFINITE);
284 screen->base.screen->fence_reference(screen->base.screen, &fence, NULL);
285 drisw_copy_to_front(ctx->st->pipe, drawable, ptex, nrects, nrects ? stack_boxes : NULL);
286 drawable->buffer_age = 1;
287
288 /* TODO: remove this if the framebuffer state doesn't change. */
289 st_context_invalidate_state(ctx->st, ST_INVALIDATE_FB_STATE);
290 }
291 }
292
293 static void
drisw_swap_buffers(struct dri_drawable * drawable)294 drisw_swap_buffers(struct dri_drawable *drawable)
295 {
296 drisw_swap_buffers_with_damage(drawable, 0, NULL);
297 }
298
299 static void
drisw_copy_sub_buffer(struct dri_drawable * drawable,int x,int y,int w,int h)300 drisw_copy_sub_buffer(struct dri_drawable *drawable, int x, int y,
301 int w, int h)
302 {
303 struct dri_context *ctx = dri_get_current();
304 struct dri_screen *screen = drawable->screen;
305 struct pipe_resource *ptex;
306 struct pipe_box box;
307 if (!ctx)
308 return;
309
310 ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
311
312 if (ptex) {
313 /* Wait for glthread to finish because we can't use pipe_context from
314 * multiple threads.
315 */
316 _mesa_glthread_finish(ctx->st->ctx);
317
318 struct pipe_fence_handle *fence = NULL;
319 if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL])
320 pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
321
322 st_context_flush(ctx->st, ST_FLUSH_FRONT, &fence, NULL, NULL);
323
324 screen->base.screen->fence_finish(screen->base.screen, ctx->st->pipe,
325 fence, OS_TIMEOUT_INFINITE);
326 screen->base.screen->fence_reference(screen->base.screen, &fence, NULL);
327
328 if (drawable->stvis.samples > 1) {
329 /* Resolve the back buffer. */
330 dri_pipe_blit(ctx->st->pipe,
331 drawable->textures[ST_ATTACHMENT_BACK_LEFT],
332 drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]);
333 }
334
335 u_box_2d(x, drawable->h - y - h, w, h, &box);
336 drisw_present_texture(ctx->st->pipe, drawable, ptex, 1, &box);
337 }
338 }
339
340 static bool
drisw_flush_frontbuffer(struct dri_context * ctx,struct dri_drawable * drawable,enum st_attachment_type statt)341 drisw_flush_frontbuffer(struct dri_context *ctx,
342 struct dri_drawable *drawable,
343 enum st_attachment_type statt)
344 {
345 struct pipe_resource *ptex;
346
347 if (!ctx || statt != ST_ATTACHMENT_FRONT_LEFT)
348 return false;
349
350 /* Wait for glthread to finish because we can't use pipe_context from
351 * multiple threads.
352 */
353 _mesa_glthread_finish(ctx->st->ctx);
354
355 if (drawable->stvis.samples > 1) {
356 /* Resolve the front buffer. */
357 dri_pipe_blit(ctx->st->pipe,
358 drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
359 drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
360 }
361 ptex = drawable->textures[statt];
362
363 if (ptex) {
364 drisw_copy_to_front(ctx->st->pipe, ctx->draw, ptex, 0, NULL);
365 }
366
367 return true;
368 }
369
370 extern bool
371 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
372 struct __DRIimageList *images,
373 const enum st_attachment_type *statts,
374 unsigned statts_count);
375
376 static void
handle_in_fence(struct dri_context * ctx,__DRIimage * img)377 handle_in_fence(struct dri_context *ctx, __DRIimage *img)
378 {
379 struct pipe_context *pipe = ctx->st->pipe;
380 struct pipe_fence_handle *fence;
381 int fd = img->in_fence_fd;
382
383 if (fd == -1)
384 return;
385
386 validate_fence_fd(fd);
387
388 img->in_fence_fd = -1;
389
390 pipe->create_fence_fd(pipe, &fence, fd, PIPE_FD_TYPE_NATIVE_SYNC);
391 pipe->fence_server_sync(pipe, fence);
392 pipe->screen->fence_reference(pipe->screen, &fence, NULL);
393
394 close(fd);
395 }
396
397 /**
398 * Allocate framebuffer attachments.
399 *
400 * During fixed-size operation, the function keeps allocating new attachments
401 * as they are requested. Unused attachments are not removed, not until the
402 * framebuffer is resized or destroyed.
403 */
404 static void
drisw_allocate_textures(struct dri_context * stctx,struct dri_drawable * drawable,const enum st_attachment_type * statts,unsigned count)405 drisw_allocate_textures(struct dri_context *stctx,
406 struct dri_drawable *drawable,
407 const enum st_attachment_type *statts,
408 unsigned count)
409 {
410 struct dri_screen *screen = drawable->screen;
411 const __DRIswrastLoaderExtension *loader = drawable->screen->swrast_loader;
412 struct pipe_resource templ;
413 unsigned width, height;
414 bool resized;
415 unsigned i;
416 const __DRIimageLoaderExtension *image = screen->image.loader;
417 struct __DRIimageList images;
418 bool imported_buffers = true;
419
420 /* Wait for glthread to finish because we can't use pipe_context from
421 * multiple threads.
422 */
423 _mesa_glthread_finish(stctx->st->ctx);
424
425 /* First try to get the buffers from the loader */
426 if (image) {
427 if (!dri_image_drawable_get_buffers(drawable, &images,
428 statts, count))
429 imported_buffers = false;
430 }
431
432 width = drawable->w;
433 height = drawable->h;
434
435 resized = (drawable->old_w != width ||
436 drawable->old_h != height);
437
438 /* remove outdated textures */
439 if (resized) {
440 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
441 pipe_resource_reference(&drawable->textures[i], NULL);
442 pipe_resource_reference(&drawable->msaa_textures[i], NULL);
443 }
444 drawable->buffer_age = 0;
445 }
446
447 memset(&templ, 0, sizeof(templ));
448 templ.target = screen->target;
449 templ.width0 = width;
450 templ.height0 = height;
451 templ.depth0 = 1;
452 templ.array_size = 1;
453 templ.last_level = 0;
454
455 if (imported_buffers && image) {
456 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
457 struct pipe_resource **buf =
458 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
459 struct pipe_resource *texture = images.front->texture;
460
461 drawable->w = texture->width0;
462 drawable->h = texture->height0;
463
464 pipe_resource_reference(buf, texture);
465 handle_in_fence(stctx, images.front);
466 }
467
468 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
469 struct pipe_resource **buf =
470 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
471 struct pipe_resource *texture = images.back->texture;
472
473 drawable->w = texture->width0;
474 drawable->h = texture->height0;
475
476 pipe_resource_reference(buf, texture);
477 handle_in_fence(stctx, images.back);
478 }
479
480 if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) {
481 struct pipe_resource **buf =
482 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
483 struct pipe_resource *texture = images.back->texture;
484
485 drawable->w = texture->width0;
486 drawable->h = texture->height0;
487
488 pipe_resource_reference(buf, texture);
489 handle_in_fence(stctx, images.back);
490 }
491
492 /* Note: if there is both a back and a front buffer,
493 * then they have the same size.
494 */
495 templ.width0 = drawable->w;
496 templ.height0 = drawable->h;
497 } else {
498 for (i = 0; i < count; i++) {
499 enum pipe_format format;
500 unsigned bind;
501
502 /* the texture already exists or not requested */
503 if (drawable->textures[statts[i]])
504 continue;
505
506 dri_drawable_get_format(drawable, statts[i], &format, &bind);
507
508 /* if we don't do any present, no need for display targets */
509 if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !screen->swrast_no_present)
510 bind |= PIPE_BIND_DISPLAY_TARGET;
511
512 if (format == PIPE_FORMAT_NONE)
513 continue;
514
515 templ.format = format;
516 templ.bind = bind;
517 templ.nr_samples = 0;
518 templ.nr_storage_samples = 0;
519
520 if (statts[i] == ST_ATTACHMENT_FRONT_LEFT &&
521 screen->base.screen->resource_create_front &&
522 loader->base.version >= 3) {
523 drawable->textures[statts[i]] =
524 screen->base.screen->resource_create_front(screen->base.screen, &templ, (const void *)drawable);
525 } else
526 drawable->textures[statts[i]] =
527 screen->base.screen->resource_create(screen->base.screen, &templ);
528
529 if (drawable->stvis.samples > 1) {
530 templ.bind = templ.bind &
531 ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET);
532 templ.nr_samples = drawable->stvis.samples;
533 templ.nr_storage_samples = drawable->stvis.samples;
534 drawable->msaa_textures[statts[i]] =
535 screen->base.screen->resource_create(screen->base.screen, &templ);
536
537 dri_pipe_blit(stctx->st->pipe,
538 drawable->msaa_textures[statts[i]],
539 drawable->textures[statts[i]]);
540 }
541 }
542 }
543
544 drawable->old_w = width;
545 drawable->old_h = height;
546 }
547
548 void
drisw_update_tex_buffer(struct dri_drawable * drawable,struct dri_context * ctx,struct pipe_resource * res)549 drisw_update_tex_buffer(struct dri_drawable *drawable,
550 struct dri_context *ctx,
551 struct pipe_resource *res)
552 {
553 struct st_context *st_ctx = (struct st_context *)ctx->st;
554 struct pipe_context *pipe = st_ctx->pipe;
555 struct pipe_transfer *transfer;
556 char *map;
557 int x, y, w, h;
558 int ximage_stride, line;
559 int cpp = util_format_get_blocksize(res->format);
560
561 /* Wait for glthread to finish because we can't use pipe_context from
562 * multiple threads.
563 */
564 _mesa_glthread_finish(ctx->st->ctx);
565
566 get_drawable_info(drawable, &x, &y, &w, &h);
567
568 map = pipe_texture_map(pipe, res,
569 0, 0, // level, layer,
570 PIPE_MAP_WRITE,
571 x, y, w, h, &transfer);
572
573 /* Copy the Drawable content to the mapped texture buffer */
574 if (!get_image_shm(drawable, x, y, w, h, res))
575 get_image(drawable, x, y, w, h, map);
576
577 /* The pipe transfer has a pitch rounded up to the nearest 64 pixels.
578 get_image() has a pitch rounded up to 4 bytes. */
579 ximage_stride = ((w * cpp) + 3) & -4;
580 for (line = h-1; line; --line) {
581 memmove(&map[line * transfer->stride],
582 &map[line * ximage_stride],
583 ximage_stride);
584 }
585
586 pipe_texture_unmap(pipe, transfer);
587 }
588
589 /*
590 * Backend function for init_screen.
591 */
592
593 static const struct drisw_loader_funcs drisw_lf = {
594 .get_image = drisw_get_image,
595 .put_image = drisw_put_image,
596 .put_image2 = drisw_put_image2
597 };
598
599 static const struct drisw_loader_funcs drisw_shm_lf = {
600 .get_image = drisw_get_image,
601 .put_image = drisw_put_image,
602 .put_image2 = drisw_put_image2,
603 .put_image_shm = drisw_put_image_shm
604 };
605
606 void
drisw_init_drawable(struct dri_drawable * drawable,bool isPixmap,int alphaBits)607 drisw_init_drawable(struct dri_drawable *drawable, bool isPixmap, int alphaBits)
608 {
609 drawable->allocate_textures = drisw_allocate_textures;
610 drawable->update_drawable_info = drisw_update_drawable_info;
611 drawable->flush_frontbuffer = drisw_flush_frontbuffer;
612 drawable->update_tex_buffer = drisw_update_tex_buffer;
613 drawable->swap_buffers = drisw_swap_buffers;
614 drawable->swap_buffers_with_damage = drisw_swap_buffers_with_damage;
615 }
616
617 struct pipe_screen *
drisw_init_screen(struct dri_screen * screen,bool driver_name_is_inferred)618 drisw_init_screen(struct dri_screen *screen, bool driver_name_is_inferred)
619 {
620 const __DRIswrastLoaderExtension *loader = screen->swrast_loader;
621 struct pipe_screen *pscreen = NULL;
622 const struct drisw_loader_funcs *lf = &drisw_lf;
623
624 screen->swrast_no_present = debug_get_option_swrast_no_present();
625
626 if (loader->base.version >= 4) {
627 if (loader->putImageShm)
628 lf = &drisw_shm_lf;
629 }
630
631 bool success = false;
632 #ifdef HAVE_DRISW_KMS
633 if (screen->fd != -1)
634 success = pipe_loader_sw_probe_kms(&screen->dev, screen->fd);
635 #endif
636 if (!success)
637 success = pipe_loader_sw_probe_dri(&screen->dev, lf);
638
639 if (success)
640 pscreen = pipe_loader_create_screen(screen->dev, driver_name_is_inferred);
641
642 return pscreen;
643 }
644
645 /* swrast copy sub buffer entrypoint. */
646 void
driswCopySubBuffer(__DRIdrawable * pdp,int x,int y,int w,int h)647 driswCopySubBuffer(__DRIdrawable *pdp, int x, int y, int w, int h)
648 {
649 struct dri_drawable *drawable = dri_drawable(pdp);
650
651 assert(drawable->screen->swrast_loader);
652
653 drisw_copy_sub_buffer(drawable, x, y, w, h);
654 }
655
656 /* vim: set sw=3 ts=8 sts=3 expandtab: */
657