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