2 * Mesa 3-D graphics library
5 * Copyright (C) 2010 LunarG Inc.
6 * Copyright (C) 2011 VMware Inc. All rights reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
27 * Chia-I Wu <olv@lunarg.com>
28 * Thomas Hellstrom <thellstrom@vmware.com>
31 #include "util/u_inlines.h"
32 #include "util/u_memory.h"
33 #include "pipe/p_screen.h"
34 #include "pipe/p_context.h"
35 #include "pipe/p_state.h"
37 #include "native_helper.h"
40 * Number of swap fences and mask
43 #define EGL_SWAP_FENCES_MAX 4
44 #define EGL_SWAP_FENCES_MASK 3
45 #define EGL_SWAP_FENCES_DEFAULT 1
47 struct resource_surface
{
48 struct pipe_screen
*screen
;
49 enum pipe_format format
;
52 struct pipe_resource
*resources
[NUM_NATIVE_ATTACHMENTS
];
59 struct pipe_fence_handle
*swap_fences
[EGL_SWAP_FENCES_MAX
];
60 unsigned int cur_fences
;
63 unsigned int desired_fences
;
66 struct resource_surface
*
67 resource_surface_create(struct pipe_screen
*screen
,
68 enum pipe_format format
, uint bind
)
70 struct resource_surface
*rsurf
= CALLOC_STRUCT(resource_surface
);
71 char *swap_fences
= getenv("EGL_THROTTLE_FENCES");
74 rsurf
->screen
= screen
;
75 rsurf
->format
= format
;
77 rsurf
->desired_fences
= (swap_fences
) ? atoi(swap_fences
) :
78 EGL_SWAP_FENCES_DEFAULT
;
79 if (rsurf
->desired_fences
> EGL_SWAP_FENCES_MAX
)
80 rsurf
->desired_fences
= EGL_SWAP_FENCES_MAX
;
87 resource_surface_free_resources(struct resource_surface
*rsurf
)
89 if (rsurf
->resource_mask
) {
92 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
93 if (rsurf
->resources
[i
])
94 pipe_resource_reference(&rsurf
->resources
[i
], NULL
);
96 rsurf
->resource_mask
= 0x0;
101 resource_surface_destroy(struct resource_surface
*rsurf
)
103 resource_surface_free_resources(rsurf
);
108 resource_surface_set_size(struct resource_surface
*rsurf
,
109 uint width
, uint height
)
111 boolean changed
= FALSE
;
113 if (rsurf
->width
!= width
|| rsurf
->height
!= height
) {
114 resource_surface_free_resources(rsurf
);
115 rsurf
->width
= width
;
116 rsurf
->height
= height
;
124 resource_surface_get_size(struct resource_surface
*rsurf
,
125 uint
*width
, uint
*height
)
128 *width
= rsurf
->width
;
130 *height
= rsurf
->height
;
134 resource_surface_add_resources(struct resource_surface
*rsurf
,
137 struct pipe_resource templ
;
140 resource_mask
&= ~rsurf
->resource_mask
;
144 if (!rsurf
->width
|| !rsurf
->height
)
147 memset(&templ
, 0, sizeof(templ
));
148 templ
.target
= PIPE_TEXTURE_2D
;
149 templ
.format
= rsurf
->format
;
150 templ
.bind
= rsurf
->bind
;
151 templ
.width0
= rsurf
->width
;
152 templ
.height0
= rsurf
->height
;
154 templ
.array_size
= 1;
156 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
157 if (resource_mask
& (1 <<i
)) {
158 assert(!rsurf
->resources
[i
]);
160 rsurf
->resources
[i
] =
161 rsurf
->screen
->resource_create(rsurf
->screen
, &templ
);
162 if (rsurf
->resources
[i
])
163 rsurf
->resource_mask
|= 1 << i
;
167 return ((rsurf
->resource_mask
& resource_mask
) == resource_mask
);
171 resource_surface_import_resource(struct resource_surface
*rsurf
,
172 enum native_attachment which
,
173 struct pipe_resource
*pres
)
175 pipe_resource_reference(&rsurf
->resources
[which
], pres
);
176 rsurf
->resource_mask
|= 1 << which
;
180 resource_surface_get_resources(struct resource_surface
*rsurf
,
181 struct pipe_resource
**resources
,
186 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
187 if (resource_mask
& (1 << i
)) {
189 pipe_resource_reference(&resources
[i
], rsurf
->resources
[i
]);
194 struct pipe_resource
*
195 resource_surface_get_single_resource(struct resource_surface
*rsurf
,
196 enum native_attachment which
)
198 struct pipe_resource
*pres
= NULL
;
199 pipe_resource_reference(&pres
, rsurf
->resources
[which
]);
204 pointer_swap(const void **p1
, const void **p2
)
206 const void *tmp
= *p1
;
212 resource_surface_swap_buffers(struct resource_surface
*rsurf
,
213 enum native_attachment buf1
,
214 enum native_attachment buf2
,
215 boolean only_if_exist
)
217 const uint buf1_bit
= 1 << buf1
;
218 const uint buf2_bit
= 1 << buf2
;
221 if (only_if_exist
&& !(rsurf
->resources
[buf1
] && rsurf
->resources
[buf2
]))
224 pointer_swap((const void **) &rsurf
->resources
[buf1
],
225 (const void **) &rsurf
->resources
[buf2
]);
228 mask
= rsurf
->resource_mask
& ~(buf1_bit
| buf2_bit
);
229 if (rsurf
->resource_mask
& buf1_bit
)
231 if (rsurf
->resource_mask
& buf2_bit
)
234 rsurf
->resource_mask
= mask
;
238 resource_surface_present(struct resource_surface
*rsurf
,
239 enum native_attachment which
,
240 void *winsys_drawable_handle
)
242 struct pipe_resource
*pres
= rsurf
->resources
[which
];
247 rsurf
->screen
->flush_frontbuffer(rsurf
->screen
,
248 pres
, 0, 0, winsys_drawable_handle
);
254 * Schedule a copy swap from the back to the front buffer using the
255 * native display's copy context.
258 resource_surface_copy_swap(struct resource_surface
*rsurf
,
259 struct native_display
*ndpy
)
261 struct pipe_resource
*ftex
;
262 struct pipe_resource
*btex
;
263 struct pipe_context
*pipe
;
264 struct pipe_box src_box
;
267 pipe
= ndpy_get_copy_context(ndpy
);
271 ftex
= resource_surface_get_single_resource(rsurf
,
272 NATIVE_ATTACHMENT_FRONT_LEFT
);
275 btex
= resource_surface_get_single_resource(rsurf
,
276 NATIVE_ATTACHMENT_BACK_LEFT
);
280 u_box_origin_2d(ftex
->width0
, ftex
->height0
, &src_box
);
281 pipe
->resource_copy_region(pipe
, ftex
, 0, 0, 0, 0,
286 pipe_resource_reference(&btex
, NULL
);
288 pipe_resource_reference(&ftex
, NULL
);
293 static struct pipe_fence_handle
*
294 swap_fences_pop_front(struct resource_surface
*rsurf
)
296 struct pipe_screen
*screen
= rsurf
->screen
;
297 struct pipe_fence_handle
*fence
= NULL
;
299 if (rsurf
->desired_fences
== 0)
302 if (rsurf
->cur_fences
>= rsurf
->desired_fences
) {
303 screen
->fence_reference(screen
, &fence
, rsurf
->swap_fences
[rsurf
->tail
]);
304 screen
->fence_reference(screen
, &rsurf
->swap_fences
[rsurf
->tail
++], NULL
);
305 rsurf
->tail
&= EGL_SWAP_FENCES_MASK
;
312 swap_fences_push_back(struct resource_surface
*rsurf
,
313 struct pipe_fence_handle
*fence
)
315 struct pipe_screen
*screen
= rsurf
->screen
;
317 if (!fence
|| rsurf
->desired_fences
== 0)
320 while(rsurf
->cur_fences
== rsurf
->desired_fences
)
321 swap_fences_pop_front(rsurf
);
324 screen
->fence_reference(screen
, &rsurf
->swap_fences
[rsurf
->head
++],
326 rsurf
->head
&= EGL_SWAP_FENCES_MASK
;
330 resource_surface_throttle(struct resource_surface
*rsurf
)
332 struct pipe_screen
*screen
= rsurf
->screen
;
333 struct pipe_fence_handle
*fence
= swap_fences_pop_front(rsurf
);
336 (void) screen
->fence_finish(screen
, fence
, PIPE_TIMEOUT_INFINITE
);
337 screen
->fence_reference(screen
, &fence
, NULL
);
345 resource_surface_flush(struct resource_surface
*rsurf
,
346 struct native_display
*ndpy
)
348 struct pipe_fence_handle
*fence
= NULL
;
349 struct pipe_screen
*screen
= rsurf
->screen
;
350 struct pipe_context
*pipe
= ndpy_get_copy_context(ndpy
);
355 pipe
->flush(pipe
, &fence
, 0);
359 swap_fences_push_back(rsurf
, fence
);
360 screen
->fence_reference(screen
, &fence
, NULL
);
366 resource_surface_wait(struct resource_surface
*rsurf
)
368 while (resource_surface_throttle(rsurf
));
372 native_display_copy_to_pixmap(struct native_display
*ndpy
,
373 EGLNativePixmapType pix
,
374 struct pipe_resource
*src
)
376 struct pipe_context
*pipe
;
377 struct native_surface
*nsurf
;
378 struct pipe_resource
*dst
;
379 struct pipe_resource
*tmp
[NUM_NATIVE_ATTACHMENTS
];
380 const enum native_attachment natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
382 pipe
= ndpy_get_copy_context(ndpy
);
386 nsurf
= ndpy
->create_pixmap_surface(ndpy
, pix
, NULL
);
390 /* get the texutre */
392 nsurf
->validate(nsurf
, 1 << natt
, NULL
, tmp
, NULL
, NULL
);
395 if (dst
&& dst
->format
== src
->format
) {
396 struct native_present_control ctrl
;
397 struct pipe_box src_box
;
399 u_box_origin_2d(src
->width0
, src
->height0
, &src_box
);
400 pipe
->resource_copy_region(pipe
, dst
, 0, 0, 0, 0, src
, 0, &src_box
);
401 pipe
->flush(pipe
, NULL
, 0);
403 memset(&ctrl
, 0, sizeof(ctrl
));
405 nsurf
->present(nsurf
, &ctrl
);
409 pipe_resource_reference(&dst
, NULL
);
411 nsurf
->destroy(nsurf
);
416 #include "state_tracker/drm_driver.h"
417 struct pipe_resource
*
418 drm_display_import_native_buffer(struct native_display
*ndpy
,
419 struct native_buffer
*nbuf
)
421 struct pipe_screen
*screen
= ndpy
->screen
;
422 struct pipe_resource
*res
= NULL
;
424 switch (nbuf
->type
) {
425 case NATIVE_BUFFER_DRM
:
427 struct winsys_handle wsh
;
429 memset(&wsh
, 0, sizeof(wsh
));
430 wsh
.handle
= nbuf
->u
.drm
.name
;
431 wsh
.stride
= nbuf
->u
.drm
.stride
;
433 res
= screen
->resource_from_handle(screen
, &nbuf
->u
.drm
.templ
, &wsh
);
444 drm_display_export_native_buffer(struct native_display
*ndpy
,
445 struct pipe_resource
*res
,
446 struct native_buffer
*nbuf
)
448 struct pipe_screen
*screen
= ndpy
->screen
;
451 switch (nbuf
->type
) {
452 case NATIVE_BUFFER_DRM
:
454 struct winsys_handle wsh
;
456 if ((nbuf
->u
.drm
.templ
.bind
& res
->bind
) != nbuf
->u
.drm
.templ
.bind
)
459 memset(&wsh
, 0, sizeof(wsh
));
460 wsh
.type
= DRM_API_HANDLE_TYPE_KMS
;
461 if (!screen
->resource_get_handle(screen
, res
, &wsh
))
464 nbuf
->u
.drm
.handle
= wsh
.handle
;
465 nbuf
->u
.drm
.stride
= wsh
.stride
;
467 /* get the name of the GEM object */
468 if (nbuf
->u
.drm
.templ
.bind
& PIPE_BIND_SHARED
) {
469 memset(&wsh
, 0, sizeof(wsh
));
470 wsh
.type
= DRM_API_HANDLE_TYPE_SHARED
;
471 if (!screen
->resource_get_handle(screen
, res
, &wsh
))
474 nbuf
->u
.drm
.name
= wsh
.handle
;
477 nbuf
->u
.drm
.templ
= *res
;