1 /**************************************************************************
3 * Copyright 2009, VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "dri_screen.h"
29 #include "dri_context.h"
30 #include "dri_swapbuffers.h"
32 #include "pipe/p_context.h"
33 #include "state_tracker/st_public.h"
34 #include "state_tracker/st_context.h"
35 #include "state_tracker/st_cb_fbo.h"
39 blit_swapbuffers(__DRIdrawablePrivate
*dPriv
,
40 __DRIcontextPrivate
*cPriv
,
41 struct pipe_surface
*src
,
42 const drm_clip_rect_t
*rect
)
44 struct dri_screen
*screen
= dri_screen(dPriv
->driScreenPriv
);
45 struct dri_drawable
*fb
= dri_drawable(dPriv
);
46 struct dri_context
*context
= dri_context(cPriv
);
48 const int nbox
= dPriv
->numClipRects
;
49 const drm_clip_rect_t
*pbox
= dPriv
->pClipRects
;
51 struct pipe_surface
*dest
= fb
->front_surface
;
52 const int backWidth
= fb
->stfb
->Base
.Width
;
53 const int backHeight
= fb
->stfb
->Base
.Height
;
56 for (i
= 0; i
< nbox
; i
++, pbox
++) {
60 if (pbox
->x1
> pbox
->x2
||
61 pbox
->y1
> pbox
->y2
||
62 (pbox
->x2
- pbox
->x1
) > dest
->width
||
63 (pbox
->y2
- pbox
->y1
) > dest
->height
)
69 drm_clip_rect_t rrect
;
71 rrect
.x1
= dPriv
->x
+ rect
->x1
;
72 rrect
.y1
= (dPriv
->h
- rect
->y1
- rect
->y2
) + dPriv
->y
;
73 rrect
.x2
= rect
->x2
+ rrect
.x1
;
74 rrect
.y2
= rect
->y2
+ rrect
.y1
;
75 if (rrect
.x1
> box
.x1
)
77 if (rrect
.y1
> box
.y1
)
79 if (rrect
.x2
< box
.x2
)
81 if (rrect
.y2
< box
.y2
)
84 if (box
.x1
> box
.x2
|| box
.y1
> box
.y2
)
88 /* restrict blit to size of actually rendered area */
89 if (box
.x2
- box
.x1
> backWidth
)
90 box
.x2
= backWidth
+ box
.x1
;
91 if (box
.y2
- box
.y1
> backHeight
)
92 box
.y2
= backHeight
+ box
.y1
;
94 debug_printf("%s: box %d,%d-%d,%d\n", __FUNCTION__
,
95 box
.x1
, box
.y1
, box
.x2
, box
.y2
);
97 sbox
.x1
= box
.x1
- dPriv
->x
;
98 sbox
.y1
= box
.y1
- dPriv
->y
;
100 ctx
->st
->pipe
->surface_copy( ctx
->st
->pipe
,
112 * Display a colorbuffer surface in an X window.
113 * Used for SwapBuffers and flushing front buffer rendering.
115 * \param dPriv the window/drawable to display into
116 * \param surf the surface to display
117 * \param rect optional subrect of surface to display (may be NULL).
120 dri_display_surface(__DRIdrawablePrivate
*dPriv
,
121 struct pipe_surface
*source
,
122 const drm_clip_rect_t
*rect
)
124 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
125 struct dri_screen
*screen
= dri_screen(dPriv
->driScreenPriv
);
126 struct dri_context
*context
= screen
->dummy_context
;
127 struct pipe_winsys
*winsys
= screen
->winsys
;
132 if (drawable
->last_swap_fence
) {
133 winsys
->fence_finish( winsys
,
134 drawable
->last_swap_fence
,
137 winsys
->fence_reference( winsys
,
138 &drawable
->last_swap_fence
,
142 drawable
->last_swap_fence
= drawable
->first_swap_fence
;
143 drawable
->first_swap_fence
= NULL
;
145 /* Call lock_hardware to update dPriv cliprects.
147 dri_lock_hardware(context
, drawable
);
149 if (dPriv
->numClipRects
) {
150 blit_swapbuffers( context
, dPriv
, source
, rect
);
153 dri_unlock_hardware(context
);
155 if (drawble
->stamp
!= drawable
->dPriv
->lastStamp
) {
156 dri_update_window_size( dpriv
);
163 * This will be called a drawable is known to have moved/resized.
166 dri_update_window_size(__DRIdrawablePrivate
*dPriv
)
168 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
169 st_resize_framebuffer(drawable
->stfb
, dPriv
->w
, dPriv
->h
);
170 drawable
->stamp
= dPriv
->lastStamp
;
176 dri_swap_buffers(__DRIdrawablePrivate
* dPriv
)
178 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
179 struct pipe_surface
*back_surf
;
182 assert(drawable
->stfb
);
184 back_surf
= st_get_framebuffer_surface(drawable
->stfb
,
185 ST_SURFACE_BACK_LEFT
);
187 st_notify_swapbuffers(drawable
->stfb
);
188 dri_display_surface(dPriv
, back_surf
, NULL
);
189 st_notify_swapbuffers_complete(drawable
->stfb
);
195 * Called via glXCopySubBufferMESA() to copy a subrect of the back
196 * buffer to the front buffer/screen.
199 dri_copy_sub_buffer(__DRIdrawablePrivate
* dPriv
, int x
, int y
, int w
, int h
)
201 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
202 struct pipe_surface
*back_surf
;
205 assert(drawable
->stfb
);
207 back_surf
= st_get_framebuffer_surface(drawable
->stfb
,
208 ST_SURFACE_BACK_LEFT
);
210 drm_clip_rect_t rect
;
216 st_notify_swapbuffers(drawable
->stfb
);
217 dri_display_surface(dPriv
, back_surf
, &rect
);
224 * The state tracker keeps track of whether the fake frontbuffer has
225 * been touched by any rendering since the last time we copied its
226 * contents to the real frontbuffer. Our task is easy:
229 dri_flush_frontbuffer( struct pipe_winsys
*winsys
,
230 struct pipe_surface
*surf
,
231 void *context_private
)
233 struct dri_context
*dri
= (struct dri_context
*) context_private
;
234 __DRIdrawablePrivate
*dPriv
= dri
->driDrawable
;
236 dri_display_surface(dPriv
, surf
, NULL
);
241 /* Need to create a surface which wraps the front surface to support
242 * client-side swapbuffers.
245 dri_create_front_surface(struct dri_screen
*screen
,
246 struct pipe_winsys
*winsys
,
249 struct pipe_screen
*pipe_screen
= screen
->pipe_screen
;
250 struct pipe_texture
*texture
;
251 struct pipe_texture templat
;
252 struct pipe_surface
*surface
;
253 struct pipe_buffer
*buffer
;
256 assert(screen
->front
.cpp
== 4);
258 // buffer = dri_buffer_from_handle(screen->winsys,
264 screen
->front
.buffer
= dri_bo(buffer
);
266 memset(&templat
, 0, sizeof(templat
));
267 templat
.tex_usage
|= PIPE_TEXTURE_USAGE_DISPLAY_TARGET
;
268 templat
.target
= PIPE_TEXTURE_2D
;
269 templat
.last_level
= 0;
270 templat
.depth
[0] = 1;
271 templat
.format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
272 templat
.width
[0] = screen
->front
.width
;
273 templat
.height
[0] = screen
->front
.height
;
274 pf_get_block(templat
.format
, &templat
.block
);
275 pitch
= screen
->front
.pitch
;
277 texture
= pipe_screen
->texture_blanket(pipe_screen
,
282 /* Unref the buffer we don't need it anyways */
283 pipe_buffer_reference(screen
, &buffer
, NULL
);
285 surface
= pipe_screen
->get_tex_surface(pipe_screen
,
290 PIPE_BUFFER_USAGE_GPU_WRITE
);
292 screen
->front
.texture
= texture
;
293 screen
->front
.surface
= surface
;
297 * This is called when we need to set up GL rendering to a new X window.
300 dri_create_buffer(__DRIscreenPrivate
*sPriv
,
301 __DRIdrawablePrivate
*dPriv
,
302 const __GLcontextModes
*visual
,
305 enum pipe_format colorFormat
, depthFormat
, stencilFormat
;
306 struct dri_drawable
*drawable
;
309 goto fail
; /* not implemented */
311 drawable
= CALLOC_STRUCT(dri_drawable
);
312 if (drawable
== NULL
)
315 /* XXX: todo: use the pipe_screen queries to figure out which
316 * render targets are supportable.
318 if (visual
->redBits
== 5)
319 colorFormat
= PIPE_FORMAT_R5G6B5_UNORM
;
321 colorFormat
= PIPE_FORMAT_A8R8G8B8_UNORM
;
323 if (visual
->depthBits
== 16)
324 depthFormat
= PIPE_FORMAT_Z16_UNORM
;
325 else if (visual
->depthBits
== 24) {
326 if (visual
->stencilBits
== 8)
327 depthFormat
= PIPE_FORMAT_S8Z24_UNORM
;
329 depthFormat
= PIPE_FORMAT_X8Z24_UNORM
;
332 drawable
->stfb
= st_create_framebuffer(visual
,
338 if (drawable
->stfb
== NULL
)
341 dPriv
->driverPrivate
= (void *) drawable
;
350 dri_destroy_buffer(__DRIdrawablePrivate
*dPriv
)
352 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
354 /* No particular need to wait on fences before dereferencing them:
356 winsys
->fence_reference( winsys
, &ctx
->last_swap_fence
, NULL
);
357 winsys
->fence_reference( winsys
, &ctx
->first_swap_fence
, NULL
);
359 st_unreference_framebuffer(drawable
->stfb
);