Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright © 2011 Intel Corporation |
||
3 | * |
||
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
5 | * copy of this software and associated documentation files (the "Software"), |
||
6 | * to deal in the Software without restriction, including without limitation |
||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
8 | * and/or sell copies of the Software, and to permit persons to whom the |
||
9 | * Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice (including the next |
||
12 | * paragraph) shall be included in all copies or substantial portions of the |
||
13 | * 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 |
||
19 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
||
20 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
22 | * DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Kristian Høgsberg |
||
26 | */ |
||
27 | |||
28 | #include |
||
29 | #include |
||
30 | #include |
||
31 | #include |
||
32 | #include |
||
33 | #include |
||
34 | #include |
||
35 | #include |
||
36 | #include |
||
37 | #include |
||
38 | |||
39 | #include "egl_dri2.h" |
||
40 | #include "egl_dri2_fallbacks.h" |
||
41 | #include "loader.h" |
||
42 | |||
43 | static struct gbm_bo * |
||
44 | lock_front_buffer(struct gbm_surface *_surf) |
||
45 | { |
||
46 | struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf; |
||
47 | struct dri2_egl_surface *dri2_surf = surf->dri_private; |
||
48 | struct gbm_dri_device *device = (struct gbm_dri_device *) _surf->gbm; |
||
49 | struct gbm_bo *bo; |
||
50 | |||
51 | if (dri2_surf->current == NULL) { |
||
52 | _eglError(EGL_BAD_SURFACE, "no front buffer"); |
||
53 | return NULL; |
||
54 | } |
||
55 | |||
56 | bo = dri2_surf->current->bo; |
||
57 | |||
58 | if (device->dri2) { |
||
59 | dri2_surf->current->locked = 1; |
||
60 | dri2_surf->current = NULL; |
||
61 | } |
||
62 | |||
63 | return bo; |
||
64 | } |
||
65 | |||
66 | static void |
||
67 | release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo) |
||
68 | { |
||
69 | struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf; |
||
70 | struct dri2_egl_surface *dri2_surf = surf->dri_private; |
||
71 | int i; |
||
72 | |||
73 | for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { |
||
74 | if (dri2_surf->color_buffers[i].bo == bo) { |
||
75 | dri2_surf->color_buffers[i].locked = 0; |
||
76 | } |
||
77 | } |
||
78 | } |
||
79 | |||
80 | static int |
||
81 | has_free_buffers(struct gbm_surface *_surf) |
||
82 | { |
||
83 | struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf; |
||
84 | struct dri2_egl_surface *dri2_surf = surf->dri_private; |
||
85 | int i; |
||
86 | |||
87 | for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) |
||
88 | if (!dri2_surf->color_buffers[i].locked) |
||
89 | return 1; |
||
90 | |||
91 | return 0; |
||
92 | } |
||
93 | |||
94 | static _EGLSurface * |
||
95 | dri2_drm_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, |
||
96 | _EGLConfig *conf, void *native_window, |
||
97 | const EGLint *attrib_list) |
||
98 | { |
||
99 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
100 | struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); |
||
101 | struct dri2_egl_surface *dri2_surf; |
||
102 | struct gbm_surface *window = native_window; |
||
103 | struct gbm_dri_surface *surf; |
||
104 | |||
105 | (void) drv; |
||
106 | |||
107 | dri2_surf = calloc(1, sizeof *dri2_surf); |
||
108 | if (!dri2_surf) { |
||
109 | _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); |
||
110 | return NULL; |
||
111 | } |
||
112 | |||
113 | if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) |
||
114 | goto cleanup_surf; |
||
115 | |||
116 | switch (type) { |
||
117 | case EGL_WINDOW_BIT: |
||
118 | if (!window) |
||
119 | return NULL; |
||
120 | surf = gbm_dri_surface(window); |
||
121 | dri2_surf->gbm_surf = surf; |
||
122 | dri2_surf->base.Width = surf->base.width; |
||
123 | dri2_surf->base.Height = surf->base.height; |
||
124 | surf->dri_private = dri2_surf; |
||
125 | break; |
||
126 | default: |
||
127 | goto cleanup_surf; |
||
128 | } |
||
129 | |||
130 | if (dri2_dpy->dri2) { |
||
131 | dri2_surf->dri_drawable = |
||
132 | (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, |
||
133 | dri2_conf->dri_double_config, |
||
134 | dri2_surf->gbm_surf); |
||
135 | |||
136 | } else { |
||
137 | assert(dri2_dpy->swrast != NULL); |
||
138 | dri2_surf->dri_drawable = |
||
139 | (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen, |
||
140 | dri2_conf->dri_double_config, |
||
141 | dri2_surf->gbm_surf); |
||
142 | |||
143 | } |
||
144 | if (dri2_surf->dri_drawable == NULL) { |
||
145 | _eglError(EGL_BAD_ALLOC, "createNewDrawable()"); |
||
146 | goto cleanup_surf; |
||
147 | } |
||
148 | |||
149 | return &dri2_surf->base; |
||
150 | |||
151 | cleanup_surf: |
||
152 | free(dri2_surf); |
||
153 | |||
154 | return NULL; |
||
155 | } |
||
156 | |||
157 | static _EGLSurface * |
||
158 | dri2_drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, |
||
159 | _EGLConfig *conf, void *native_window, |
||
160 | const EGLint *attrib_list) |
||
161 | { |
||
162 | return dri2_drm_create_surface(drv, disp, EGL_WINDOW_BIT, conf, |
||
163 | native_window, attrib_list); |
||
164 | } |
||
165 | |||
166 | static _EGLSurface * |
||
167 | dri2_drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, |
||
168 | _EGLConfig *conf, void *native_window, |
||
169 | const EGLint *attrib_list) |
||
170 | { |
||
171 | /* From the EGL_MESA_platform_gbm spec, version 5: |
||
172 | * |
||
173 | * It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a |
||
174 | * that belongs to the GBM platform. Any such call fails and generates |
||
175 | * EGL_BAD_PARAMETER. |
||
176 | */ |
||
177 | _eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on GBM"); |
||
178 | return NULL; |
||
179 | } |
||
180 | |||
181 | static EGLBoolean |
||
182 | dri2_drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) |
||
183 | { |
||
184 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
185 | struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); |
||
186 | int i; |
||
187 | |||
188 | if (!_eglPutSurface(surf)) |
||
189 | return EGL_TRUE; |
||
190 | |||
191 | (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); |
||
192 | |||
193 | for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { |
||
194 | if (dri2_surf->color_buffers[i].bo) |
||
195 | gbm_bo_destroy(dri2_surf->color_buffers[i].bo); |
||
196 | } |
||
197 | |||
198 | for (i = 0; i < __DRI_BUFFER_COUNT; i++) { |
||
199 | if (dri2_surf->dri_buffers[i]) |
||
200 | dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, |
||
201 | dri2_surf->dri_buffers[i]); |
||
202 | } |
||
203 | |||
204 | free(surf); |
||
205 | |||
206 | return EGL_TRUE; |
||
207 | } |
||
208 | |||
209 | static int |
||
210 | get_back_bo(struct dri2_egl_surface *dri2_surf) |
||
211 | { |
||
212 | struct dri2_egl_display *dri2_dpy = |
||
213 | dri2_egl_display(dri2_surf->base.Resource.Display); |
||
214 | struct gbm_dri_surface *surf = dri2_surf->gbm_surf; |
||
215 | int i; |
||
216 | |||
217 | if (dri2_surf->back == NULL) { |
||
218 | for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { |
||
219 | if (!dri2_surf->color_buffers[i].locked) { |
||
220 | dri2_surf->back = &dri2_surf->color_buffers[i]; |
||
221 | break; |
||
222 | } |
||
223 | } |
||
224 | } |
||
225 | |||
226 | if (dri2_surf->back == NULL) |
||
227 | return -1; |
||
228 | if (dri2_surf->back->bo == NULL) |
||
229 | dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base, |
||
230 | surf->base.width, surf->base.height, |
||
231 | surf->base.format, surf->base.flags); |
||
232 | if (dri2_surf->back->bo == NULL) |
||
233 | return -1; |
||
234 | |||
235 | return 0; |
||
236 | } |
||
237 | |||
238 | static int |
||
239 | get_swrast_front_bo(struct dri2_egl_surface *dri2_surf) |
||
240 | { |
||
241 | struct dri2_egl_display *dri2_dpy = |
||
242 | dri2_egl_display(dri2_surf->base.Resource.Display); |
||
243 | struct gbm_dri_surface *surf = dri2_surf->gbm_surf; |
||
244 | |||
245 | if (dri2_surf->current == NULL) { |
||
246 | assert(!dri2_surf->color_buffers[0].locked); |
||
247 | dri2_surf->current = &dri2_surf->color_buffers[0]; |
||
248 | } |
||
249 | |||
250 | if (dri2_surf->current->bo == NULL) |
||
251 | dri2_surf->current->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base, |
||
252 | surf->base.width, surf->base.height, |
||
253 | surf->base.format, surf->base.flags); |
||
254 | if (dri2_surf->current->bo == NULL) |
||
255 | return -1; |
||
256 | |||
257 | return 0; |
||
258 | } |
||
259 | |||
260 | static void |
||
261 | back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer) |
||
262 | { |
||
263 | struct dri2_egl_display *dri2_dpy = |
||
264 | dri2_egl_display(dri2_surf->base.Resource.Display); |
||
265 | struct gbm_dri_bo *bo; |
||
266 | int name, pitch; |
||
267 | |||
268 | bo = (struct gbm_dri_bo *) dri2_surf->back->bo; |
||
269 | |||
270 | dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name); |
||
271 | dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch); |
||
272 | |||
273 | buffer->attachment = __DRI_BUFFER_BACK_LEFT; |
||
274 | buffer->name = name; |
||
275 | buffer->pitch = pitch; |
||
276 | buffer->cpp = 4; |
||
277 | buffer->flags = 0; |
||
278 | } |
||
279 | |||
280 | static int |
||
281 | get_aux_bo(struct dri2_egl_surface *dri2_surf, |
||
282 | unsigned int attachment, unsigned int format, __DRIbuffer *buffer) |
||
283 | { |
||
284 | struct dri2_egl_display *dri2_dpy = |
||
285 | dri2_egl_display(dri2_surf->base.Resource.Display); |
||
286 | __DRIbuffer *b = dri2_surf->dri_buffers[attachment]; |
||
287 | |||
288 | if (b == NULL) { |
||
289 | b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, |
||
290 | attachment, format, |
||
291 | dri2_surf->base.Width, |
||
292 | dri2_surf->base.Height); |
||
293 | dri2_surf->dri_buffers[attachment] = b; |
||
294 | } |
||
295 | if (b == NULL) |
||
296 | return -1; |
||
297 | |||
298 | memcpy(buffer, b, sizeof *buffer); |
||
299 | |||
300 | return 0; |
||
301 | } |
||
302 | |||
303 | static __DRIbuffer * |
||
304 | dri2_drm_get_buffers_with_format(__DRIdrawable *driDrawable, |
||
305 | int *width, int *height, |
||
306 | unsigned int *attachments, int count, |
||
307 | int *out_count, void *loaderPrivate) |
||
308 | { |
||
309 | struct dri2_egl_surface *dri2_surf = loaderPrivate; |
||
310 | int i, j; |
||
311 | |||
312 | dri2_surf->buffer_count = 0; |
||
313 | for (i = 0, j = 0; i < 2 * count; i += 2, j++) { |
||
314 | assert(attachments[i] < __DRI_BUFFER_COUNT); |
||
315 | assert(dri2_surf->buffer_count < 5); |
||
316 | |||
317 | switch (attachments[i]) { |
||
318 | case __DRI_BUFFER_BACK_LEFT: |
||
319 | if (get_back_bo(dri2_surf) < 0) { |
||
320 | _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer"); |
||
321 | return NULL; |
||
322 | } |
||
323 | back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]); |
||
324 | break; |
||
325 | default: |
||
326 | if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1], |
||
327 | &dri2_surf->buffers[j]) < 0) { |
||
328 | _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer"); |
||
329 | return NULL; |
||
330 | } |
||
331 | break; |
||
332 | } |
||
333 | } |
||
334 | |||
335 | *out_count = j; |
||
336 | if (j == 0) |
||
337 | return NULL; |
||
338 | |||
339 | *width = dri2_surf->base.Width; |
||
340 | *height = dri2_surf->base.Height; |
||
341 | |||
342 | return dri2_surf->buffers; |
||
343 | } |
||
344 | |||
345 | static __DRIbuffer * |
||
346 | dri2_drm_get_buffers(__DRIdrawable * driDrawable, |
||
347 | int *width, int *height, |
||
348 | unsigned int *attachments, int count, |
||
349 | int *out_count, void *loaderPrivate) |
||
350 | { |
||
351 | unsigned int *attachments_with_format; |
||
352 | __DRIbuffer *buffer; |
||
353 | const unsigned int format = 32; |
||
354 | int i; |
||
355 | |||
356 | attachments_with_format = calloc(count, 2 * sizeof(unsigned int)); |
||
357 | if (!attachments_with_format) { |
||
358 | *out_count = 0; |
||
359 | return NULL; |
||
360 | } |
||
361 | |||
362 | for (i = 0; i < count; ++i) { |
||
363 | attachments_with_format[2*i] = attachments[i]; |
||
364 | attachments_with_format[2*i + 1] = format; |
||
365 | } |
||
366 | |||
367 | buffer = |
||
368 | dri2_drm_get_buffers_with_format(driDrawable, |
||
369 | width, height, |
||
370 | attachments_with_format, count, |
||
371 | out_count, loaderPrivate); |
||
372 | |||
373 | free(attachments_with_format); |
||
374 | |||
375 | return buffer; |
||
376 | } |
||
377 | |||
378 | static int |
||
379 | dri2_drm_image_get_buffers(__DRIdrawable *driDrawable, |
||
380 | unsigned int format, |
||
381 | uint32_t *stamp, |
||
382 | void *loaderPrivate, |
||
383 | uint32_t buffer_mask, |
||
384 | struct __DRIimageList *buffers) |
||
385 | { |
||
386 | struct dri2_egl_surface *dri2_surf = loaderPrivate; |
||
387 | struct gbm_dri_bo *bo; |
||
388 | |||
389 | if (get_back_bo(dri2_surf) < 0) |
||
390 | return 0; |
||
391 | |||
392 | bo = (struct gbm_dri_bo *) dri2_surf->back->bo; |
||
393 | buffers->image_mask = __DRI_IMAGE_BUFFER_BACK; |
||
394 | buffers->back = bo->image; |
||
395 | |||
396 | return 1; |
||
397 | } |
||
398 | |||
399 | static void |
||
400 | dri2_drm_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) |
||
401 | { |
||
402 | (void) driDrawable; |
||
403 | (void) loaderPrivate; |
||
404 | } |
||
405 | |||
406 | static EGLBoolean |
||
407 | dri2_drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) |
||
408 | { |
||
409 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
410 | struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); |
||
411 | int i; |
||
412 | |||
413 | if (dri2_dpy->swrast) { |
||
414 | (*dri2_dpy->core->swapBuffers)(dri2_surf->dri_drawable); |
||
415 | } else { |
||
416 | if (dri2_surf->base.Type == EGL_WINDOW_BIT) { |
||
417 | if (dri2_surf->current) |
||
418 | _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers"); |
||
419 | for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) |
||
420 | if (dri2_surf->color_buffers[i].age > 0) |
||
421 | dri2_surf->color_buffers[i].age++; |
||
422 | |||
423 | /* Make sure we have a back buffer in case we're swapping without |
||
424 | * ever rendering. */ |
||
425 | if (get_back_bo(dri2_surf) < 0) { |
||
426 | _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers"); |
||
427 | return EGL_FALSE; |
||
428 | } |
||
429 | |||
430 | dri2_surf->current = dri2_surf->back; |
||
431 | dri2_surf->current->age = 1; |
||
432 | dri2_surf->back = NULL; |
||
433 | } |
||
434 | |||
435 | dri2_flush_drawable_for_swapbuffers(disp, draw); |
||
436 | (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); |
||
437 | } |
||
438 | |||
439 | return EGL_TRUE; |
||
440 | } |
||
441 | |||
442 | static EGLint |
||
443 | dri2_drm_query_buffer_age(_EGLDriver *drv, |
||
444 | _EGLDisplay *disp, _EGLSurface *surface) |
||
445 | { |
||
446 | struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface); |
||
447 | |||
448 | if (get_back_bo(dri2_surf) < 0) { |
||
449 | _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age"); |
||
450 | return 0; |
||
451 | } |
||
452 | |||
453 | return dri2_surf->back->age; |
||
454 | } |
||
455 | |||
456 | static _EGLImage * |
||
457 | dri2_drm_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, |
||
458 | EGLClientBuffer buffer, const EGLint *attr_list) |
||
459 | { |
||
460 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
461 | struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer); |
||
462 | struct dri2_egl_image *dri2_img; |
||
463 | |||
464 | dri2_img = malloc(sizeof *dri2_img); |
||
465 | if (!dri2_img) { |
||
466 | _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap"); |
||
467 | return NULL; |
||
468 | } |
||
469 | |||
470 | if (!_eglInitImage(&dri2_img->base, disp)) { |
||
471 | free(dri2_img); |
||
472 | return NULL; |
||
473 | } |
||
474 | |||
475 | dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img); |
||
476 | if (dri2_img->dri_image == NULL) { |
||
477 | free(dri2_img); |
||
478 | _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap"); |
||
479 | return NULL; |
||
480 | } |
||
481 | |||
482 | return &dri2_img->base; |
||
483 | } |
||
484 | |||
485 | static _EGLImage * |
||
486 | dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, |
||
487 | _EGLContext *ctx, EGLenum target, |
||
488 | EGLClientBuffer buffer, const EGLint *attr_list) |
||
489 | { |
||
490 | (void) drv; |
||
491 | |||
492 | switch (target) { |
||
493 | case EGL_NATIVE_PIXMAP_KHR: |
||
494 | return dri2_drm_create_image_khr_pixmap(disp, ctx, buffer, attr_list); |
||
495 | default: |
||
496 | return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); |
||
497 | } |
||
498 | } |
||
499 | |||
500 | #if 0 |
||
501 | static int |
||
502 | dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id) |
||
503 | { |
||
504 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
505 | |||
506 | return drmAuthMagic(dri2_dpy->fd, id); |
||
507 | } |
||
508 | #endif |
||
509 | |||
510 | static void |
||
511 | swrast_put_image2(__DRIdrawable *driDrawable, |
||
512 | int op, |
||
513 | int x, |
||
514 | int y, |
||
515 | int width, |
||
516 | int height, |
||
517 | int stride, |
||
518 | char *data, |
||
519 | void *loaderPrivate) |
||
520 | { |
||
521 | struct dri2_egl_surface *dri2_surf = loaderPrivate; |
||
522 | int internal_stride, i; |
||
523 | struct gbm_dri_bo *bo; |
||
524 | |||
525 | if (op != __DRI_SWRAST_IMAGE_OP_DRAW && |
||
526 | op != __DRI_SWRAST_IMAGE_OP_SWAP) |
||
527 | return; |
||
528 | |||
529 | if (get_swrast_front_bo(dri2_surf) < 0) |
||
530 | return; |
||
531 | |||
532 | bo = gbm_dri_bo(dri2_surf->current->bo); |
||
533 | if (gbm_dri_bo_map(bo) == NULL) |
||
534 | return; |
||
535 | |||
536 | internal_stride = bo->base.base.stride; |
||
537 | |||
538 | for (i = 0; i < height; i++) { |
||
539 | memcpy(bo->map + (x + i) * internal_stride + y, |
||
540 | data + i * stride, stride); |
||
541 | } |
||
542 | |||
543 | gbm_dri_bo_unmap(bo); |
||
544 | } |
||
545 | |||
546 | static void |
||
547 | swrast_get_image(__DRIdrawable *driDrawable, |
||
548 | int x, |
||
549 | int y, |
||
550 | int width, |
||
551 | int height, |
||
552 | char *data, |
||
553 | void *loaderPrivate) |
||
554 | { |
||
555 | struct dri2_egl_surface *dri2_surf = loaderPrivate; |
||
556 | int internal_stride, stride, i; |
||
557 | struct gbm_dri_bo *bo; |
||
558 | |||
559 | if (get_swrast_front_bo(dri2_surf) < 0) |
||
560 | return; |
||
561 | |||
562 | bo = gbm_dri_bo(dri2_surf->current->bo); |
||
563 | if (gbm_dri_bo_map(bo) == NULL) |
||
564 | return; |
||
565 | |||
566 | internal_stride = bo->base.base.stride; |
||
567 | stride = width * 4; |
||
568 | |||
569 | for (i = 0; i < height; i++) { |
||
570 | memcpy(data + i * stride, |
||
571 | bo->map + (x + i) * internal_stride + y, stride); |
||
572 | } |
||
573 | |||
574 | gbm_dri_bo_unmap(bo); |
||
575 | } |
||
576 | |||
577 | static struct dri2_egl_display_vtbl dri2_drm_display_vtbl = { |
||
578 | .authenticate = dri2_drm_authenticate, |
||
579 | .create_window_surface = dri2_drm_create_window_surface, |
||
580 | .create_pixmap_surface = dri2_drm_create_pixmap_surface, |
||
581 | .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface, |
||
582 | .destroy_surface = dri2_drm_destroy_surface, |
||
583 | .create_image = dri2_drm_create_image_khr, |
||
584 | .swap_interval = dri2_fallback_swap_interval, |
||
585 | .swap_buffers = dri2_drm_swap_buffers, |
||
586 | .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, |
||
587 | .swap_buffers_region = dri2_fallback_swap_buffers_region, |
||
588 | .post_sub_buffer = dri2_fallback_post_sub_buffer, |
||
589 | .copy_buffers = dri2_fallback_copy_buffers, |
||
590 | .query_buffer_age = dri2_drm_query_buffer_age, |
||
591 | .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, |
||
592 | .get_sync_values = dri2_fallback_get_sync_values, |
||
593 | }; |
||
594 | |||
595 | EGLBoolean |
||
596 | dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp) |
||
597 | { |
||
598 | struct dri2_egl_display *dri2_dpy; |
||
599 | struct gbm_device *gbm; |
||
600 | void *lib; |
||
601 | |||
602 | int fd = -1; |
||
603 | int i; |
||
604 | |||
605 | loader_set_logger(_eglLog); |
||
606 | |||
607 | dri2_dpy = calloc(1, sizeof *dri2_dpy); |
||
608 | if (!dri2_dpy) |
||
609 | return _eglError(EGL_BAD_ALLOC, "eglInitialize"); |
||
610 | |||
611 | disp->DriverData = (void *) dri2_dpy; |
||
612 | |||
613 | gbm = disp->PlatformDisplay; |
||
614 | if (gbm == NULL) { |
||
615 | fd = get_service("DISPLAY"); |
||
616 | dri2_dpy->own_device = 1; |
||
617 | gbm = gbm_create_device(fd); |
||
618 | if (gbm == NULL) |
||
619 | return EGL_FALSE; |
||
620 | } |
||
621 | |||
622 | if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) { |
||
623 | free(dri2_dpy); |
||
624 | return EGL_FALSE; |
||
625 | } |
||
626 | |||
627 | dri2_dpy->gbm_dri = gbm_dri_device(gbm); |
||
628 | if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) { |
||
629 | free(dri2_dpy); |
||
630 | return EGL_FALSE; |
||
631 | } |
||
632 | |||
633 | if (fd < 0) { |
||
634 | fd = dup(gbm_device_get_fd(gbm)); |
||
635 | if (fd < 0) { |
||
636 | free(dri2_dpy); |
||
637 | return EGL_FALSE; |
||
638 | } |
||
639 | } |
||
640 | |||
641 | dri2_dpy->fd = fd; |
||
642 | dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd); |
||
643 | dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->base.driver_name); |
||
644 | |||
645 | dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen; |
||
646 | dri2_dpy->core = dri2_dpy->gbm_dri->core; |
||
647 | dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2; |
||
648 | dri2_dpy->image = dri2_dpy->gbm_dri->image; |
||
649 | dri2_dpy->flush = dri2_dpy->gbm_dri->flush; |
||
650 | dri2_dpy->swrast = dri2_dpy->gbm_dri->swrast; |
||
651 | dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs; |
||
652 | |||
653 | dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image; |
||
654 | dri2_dpy->gbm_dri->lookup_user_data = disp; |
||
655 | |||
656 | dri2_dpy->gbm_dri->get_buffers = dri2_drm_get_buffers; |
||
657 | dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer; |
||
658 | dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format; |
||
659 | dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers; |
||
660 | dri2_dpy->gbm_dri->swrast_put_image2 = swrast_put_image2; |
||
661 | dri2_dpy->gbm_dri->swrast_get_image = swrast_get_image; |
||
662 | |||
663 | dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer; |
||
664 | dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer; |
||
665 | dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers; |
||
666 | |||
667 | dri2_setup_screen(disp); |
||
668 | |||
669 | for (i = 0; dri2_dpy->driver_configs[i]; i++) { |
||
670 | EGLint format, attr_list[3]; |
||
671 | unsigned int red, alpha; |
||
672 | |||
673 | dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i], |
||
674 | __DRI_ATTRIB_RED_MASK, &red); |
||
675 | dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i], |
||
676 | __DRI_ATTRIB_ALPHA_MASK, &alpha); |
||
677 | if (red == 0x3ff00000 && alpha == 0x00000000) |
||
678 | format = GBM_FORMAT_XRGB2101010; |
||
679 | else if (red == 0x3ff00000 && alpha == 0xc0000000) |
||
680 | format = GBM_FORMAT_ARGB2101010; |
||
681 | else if (red == 0x00ff0000 && alpha == 0x00000000) |
||
682 | format = GBM_FORMAT_XRGB8888; |
||
683 | else if (red == 0x00ff0000 && alpha == 0xff000000) |
||
684 | format = GBM_FORMAT_ARGB8888; |
||
685 | else if (red == 0xf800) |
||
686 | format = GBM_FORMAT_RGB565; |
||
687 | else |
||
688 | continue; |
||
689 | |||
690 | attr_list[0] = EGL_NATIVE_VISUAL_ID; |
||
691 | attr_list[1] = format; |
||
692 | attr_list[2] = EGL_NONE; |
||
693 | |||
694 | dri2_add_config(disp, dri2_dpy->driver_configs[i], |
||
695 | i + 1, EGL_WINDOW_BIT, attr_list, NULL); |
||
696 | } |
||
697 | |||
698 | disp->Extensions.KHR_image_pixmap = EGL_TRUE; |
||
699 | if (dri2_dpy->dri2) |
||
700 | disp->Extensions.EXT_buffer_age = EGL_TRUE; |
||
701 | |||
702 | #ifdef HAVE_WAYLAND_PLATFORM |
||
703 | if (dri2_dpy->image) { |
||
704 | if (dri2_dpy->image->base.version >= 10 && |
||
705 | dri2_dpy->image->getCapabilities != NULL) { |
||
706 | int capabilities; |
||
707 | |||
708 | capabilities = |
||
709 | dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); |
||
710 | disp->Extensions.WL_bind_wayland_display = |
||
711 | (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; |
||
712 | } else |
||
713 | disp->Extensions.WL_bind_wayland_display = EGL_TRUE; |
||
714 | } |
||
715 | #endif |
||
716 | |||
717 | /* we're supporting EGL 1.4 */ |
||
718 | disp->VersionMajor = 1; |
||
719 | disp->VersionMinor = 4; |
||
720 | |||
721 | /* Fill vtbl last to prevent accidentally calling virtual function during |
||
722 | * initialization. |
||
723 | */ |
||
724 | dri2_dpy->vtbl = &dri2_drm_display_vtbl; |
||
725 | |||
726 | return EGL_TRUE; |
||
727 | }>>>>>>>>>>>>>>>>>>>>> |