2 * Mesa 3-D graphics library
4 * Copyright (C) 2010 LunarG Inc.
5 * Copyright (C) 2011 VMware Inc. All rights reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 * Chia-I Wu <olv@lunarg.com>
27 * Thomas Hellstrom <thellstrom@vmware.com>
30 #include "util/u_inlines.h"
31 #include "util/u_memory.h"
32 #include "pipe/p_screen.h"
33 #include "pipe/p_context.h"
34 #include "pipe/p_state.h"
36 #include "native_helper.h"
39 * Number of swap fences and mask
42 #define EGL_SWAP_FENCES_MAX 4
43 #define EGL_SWAP_FENCES_MASK 3
44 #define EGL_SWAP_FENCES_DEFAULT 1
46 struct resource_surface
{
47 struct pipe_screen
*screen
;
48 enum pipe_format format
;
51 struct pipe_resource
*resources
[NUM_NATIVE_ATTACHMENTS
];
58 struct pipe_fence_handle
*swap_fences
[EGL_SWAP_FENCES_MAX
];
59 unsigned int cur_fences
;
62 unsigned int desired_fences
;
65 struct resource_surface
*
66 resource_surface_create(struct pipe_screen
*screen
,
67 enum pipe_format format
, uint bind
)
69 struct resource_surface
*rsurf
= CALLOC_STRUCT(resource_surface
);
70 char *swap_fences
= getenv("EGL_THROTTLE_FENCES");
73 rsurf
->screen
= screen
;
74 rsurf
->format
= format
;
76 rsurf
->desired_fences
= (swap_fences
) ? atoi(swap_fences
) :
77 EGL_SWAP_FENCES_DEFAULT
;
78 if (rsurf
->desired_fences
> EGL_SWAP_FENCES_MAX
)
79 rsurf
->desired_fences
= EGL_SWAP_FENCES_MAX
;
86 resource_surface_free_resources(struct resource_surface
*rsurf
)
88 if (rsurf
->resource_mask
) {
91 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
92 if (rsurf
->resources
[i
])
93 pipe_resource_reference(&rsurf
->resources
[i
], NULL
);
95 rsurf
->resource_mask
= 0x0;
100 resource_surface_destroy(struct resource_surface
*rsurf
)
102 resource_surface_free_resources(rsurf
);
107 resource_surface_set_size(struct resource_surface
*rsurf
,
108 uint width
, uint height
)
110 boolean changed
= FALSE
;
112 if (rsurf
->width
!= width
|| rsurf
->height
!= height
) {
113 resource_surface_free_resources(rsurf
);
114 rsurf
->width
= width
;
115 rsurf
->height
= height
;
123 resource_surface_get_size(struct resource_surface
*rsurf
,
124 uint
*width
, uint
*height
)
127 *width
= rsurf
->width
;
129 *height
= rsurf
->height
;
133 resource_surface_add_resources(struct resource_surface
*rsurf
,
136 struct pipe_resource templ
;
139 resource_mask
&= ~rsurf
->resource_mask
;
143 if (!rsurf
->width
|| !rsurf
->height
)
146 memset(&templ
, 0, sizeof(templ
));
147 templ
.target
= PIPE_TEXTURE_2D
;
148 templ
.format
= rsurf
->format
;
149 templ
.bind
= rsurf
->bind
;
150 templ
.width0
= rsurf
->width
;
151 templ
.height0
= rsurf
->height
;
153 templ
.array_size
= 1;
155 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
156 if (resource_mask
& (1 <<i
)) {
157 assert(!rsurf
->resources
[i
]);
159 rsurf
->resources
[i
] =
160 rsurf
->screen
->resource_create(rsurf
->screen
, &templ
);
161 if (rsurf
->resources
[i
])
162 rsurf
->resource_mask
|= 1 << i
;
166 return ((rsurf
->resource_mask
& resource_mask
) == resource_mask
);
170 resource_surface_import_resource(struct resource_surface
*rsurf
,
171 enum native_attachment which
,
172 struct pipe_resource
*pres
)
174 pipe_resource_reference(&rsurf
->resources
[which
], pres
);
175 rsurf
->resource_mask
|= 1 << which
;
179 resource_surface_get_resources(struct resource_surface
*rsurf
,
180 struct pipe_resource
**resources
,
185 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
186 if (resource_mask
& (1 << i
)) {
188 pipe_resource_reference(&resources
[i
], rsurf
->resources
[i
]);
193 struct pipe_resource
*
194 resource_surface_get_single_resource(struct resource_surface
*rsurf
,
195 enum native_attachment which
)
197 struct pipe_resource
*pres
= NULL
;
198 pipe_resource_reference(&pres
, rsurf
->resources
[which
]);
203 pointer_swap(const void **p1
, const void **p2
)
205 const void *tmp
= *p1
;
211 resource_surface_swap_buffers(struct resource_surface
*rsurf
,
212 enum native_attachment buf1
,
213 enum native_attachment buf2
,
214 boolean only_if_exist
)
216 const uint buf1_bit
= 1 << buf1
;
217 const uint buf2_bit
= 1 << buf2
;
220 if (only_if_exist
&& !(rsurf
->resources
[buf1
] && rsurf
->resources
[buf2
]))
223 pointer_swap((const void **) &rsurf
->resources
[buf1
],
224 (const void **) &rsurf
->resources
[buf2
]);
227 mask
= rsurf
->resource_mask
& ~(buf1_bit
| buf2_bit
);
228 if (rsurf
->resource_mask
& buf1_bit
)
230 if (rsurf
->resource_mask
& buf2_bit
)
233 rsurf
->resource_mask
= mask
;
237 resource_surface_present(struct resource_surface
*rsurf
,
238 enum native_attachment which
,
239 void *winsys_drawable_handle
)
241 struct pipe_resource
*pres
= rsurf
->resources
[which
];
246 rsurf
->screen
->flush_frontbuffer(rsurf
->screen
,
247 pres
, 0, 0, winsys_drawable_handle
, NULL
);
253 * Schedule a copy swap from the back to the front buffer using the
254 * native display's copy context.
257 resource_surface_copy_swap(struct resource_surface
*rsurf
,
258 struct native_display
*ndpy
)
260 struct pipe_resource
*ftex
;
261 struct pipe_resource
*btex
;
262 struct pipe_context
*pipe
;
263 struct pipe_box src_box
;
266 pipe
= ndpy_get_copy_context(ndpy
);
270 ftex
= resource_surface_get_single_resource(rsurf
,
271 NATIVE_ATTACHMENT_FRONT_LEFT
);
274 btex
= resource_surface_get_single_resource(rsurf
,
275 NATIVE_ATTACHMENT_BACK_LEFT
);
279 u_box_origin_2d(ftex
->width0
, ftex
->height0
, &src_box
);
280 pipe
->resource_copy_region(pipe
, ftex
, 0, 0, 0, 0,
285 pipe_resource_reference(&btex
, NULL
);
287 pipe_resource_reference(&ftex
, NULL
);
292 static struct pipe_fence_handle
*
293 swap_fences_pop_front(struct resource_surface
*rsurf
)
295 struct pipe_screen
*screen
= rsurf
->screen
;
296 struct pipe_fence_handle
*fence
= NULL
;
298 if (rsurf
->desired_fences
== 0)
301 if (rsurf
->cur_fences
>= rsurf
->desired_fences
) {
302 screen
->fence_reference(screen
, &fence
, rsurf
->swap_fences
[rsurf
->tail
]);
303 screen
->fence_reference(screen
, &rsurf
->swap_fences
[rsurf
->tail
++], NULL
);
304 rsurf
->tail
&= EGL_SWAP_FENCES_MASK
;
311 swap_fences_push_back(struct resource_surface
*rsurf
,
312 struct pipe_fence_handle
*fence
)
314 struct pipe_screen
*screen
= rsurf
->screen
;
316 if (!fence
|| rsurf
->desired_fences
== 0)
319 while(rsurf
->cur_fences
== rsurf
->desired_fences
)
320 swap_fences_pop_front(rsurf
);
323 screen
->fence_reference(screen
, &rsurf
->swap_fences
[rsurf
->head
++],
325 rsurf
->head
&= EGL_SWAP_FENCES_MASK
;
329 resource_surface_throttle(struct resource_surface
*rsurf
)
331 struct pipe_screen
*screen
= rsurf
->screen
;
332 struct pipe_fence_handle
*fence
= swap_fences_pop_front(rsurf
);
335 (void) screen
->fence_finish(screen
, fence
, PIPE_TIMEOUT_INFINITE
);
336 screen
->fence_reference(screen
, &fence
, NULL
);
344 resource_surface_flush(struct resource_surface
*rsurf
,
345 struct native_display
*ndpy
)
347 struct pipe_fence_handle
*fence
= NULL
;
348 struct pipe_screen
*screen
= rsurf
->screen
;
349 struct pipe_context
*pipe
= ndpy_get_copy_context(ndpy
);
354 pipe
->flush(pipe
, &fence
, 0);
358 swap_fences_push_back(rsurf
, fence
);
359 screen
->fence_reference(screen
, &fence
, NULL
);
365 resource_surface_wait(struct resource_surface
*rsurf
)
367 while (resource_surface_throttle(rsurf
));
371 native_display_copy_to_pixmap(struct native_display
*ndpy
,
372 EGLNativePixmapType pix
,
373 struct pipe_resource
*src
)
375 struct pipe_context
*pipe
;
376 struct native_surface
*nsurf
;
377 struct pipe_resource
*dst
;
378 struct pipe_resource
*tmp
[NUM_NATIVE_ATTACHMENTS
];
379 const enum native_attachment natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
381 pipe
= ndpy_get_copy_context(ndpy
);
385 nsurf
= ndpy
->create_pixmap_surface(ndpy
, pix
, NULL
);
389 /* get the texutre */
391 nsurf
->validate(nsurf
, 1 << natt
, NULL
, tmp
, NULL
, NULL
);
394 if (dst
&& dst
->format
== src
->format
) {
395 struct native_present_control ctrl
;
396 struct pipe_box src_box
;
398 u_box_origin_2d(src
->width0
, src
->height0
, &src_box
);
399 pipe
->resource_copy_region(pipe
, dst
, 0, 0, 0, 0, src
, 0, &src_box
);
400 pipe
->flush(pipe
, NULL
, 0);
402 memset(&ctrl
, 0, sizeof(ctrl
));
404 nsurf
->present(nsurf
, &ctrl
);
408 pipe_resource_reference(&dst
, NULL
);
410 nsurf
->destroy(nsurf
);
415 #include "state_tracker/drm_driver.h"
416 struct pipe_resource
*
417 drm_display_import_native_buffer(struct native_display
*ndpy
,
418 struct native_buffer
*nbuf
)
420 struct pipe_screen
*screen
= ndpy
->screen
;
421 struct pipe_resource
*res
= NULL
;
423 switch (nbuf
->type
) {
424 case NATIVE_BUFFER_DRM
:
426 struct winsys_handle wsh
;
428 memset(&wsh
, 0, sizeof(wsh
));
429 wsh
.handle
= nbuf
->u
.drm
.name
;
430 wsh
.type
= DRM_API_HANDLE_TYPE_SHARED
;
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
;