Use write posting in the kickoff function too.
[mesa.git] / src / mesa / drivers / dri / nouveau_winsys / nouveau_swapbuffers.c
1 #include "context.h"
2
3 #include "pipe/p_context.h"
4 #include "state_tracker/st_public.h"
5 #include "state_tracker/st_cb_fbo.h"
6
7 #include "nouveau_context.h"
8 #include "nouveau_local.h"
9 #include "nouveau_screen.h"
10 #include "nouveau_swapbuffers.h"
11
12 void
13 nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
14 const drm_clip_rect_t *rect)
15 {
16 struct nouveau_context *nv = dPriv->driContextPriv->driverPrivate;
17 struct nouveau_screen *nv_screen = nv->nv_screen;
18 struct pipe_region *p_region = surf->region;
19 drm_clip_rect_t *pbox;
20 int nbox, i;
21
22 LOCK_HARDWARE(nv);
23 if (!dPriv->numClipRects) {
24 UNLOCK_HARDWARE(nv);
25 return;
26 }
27 pbox = dPriv->pClipRects;
28 nbox = dPriv->numClipRects;
29
30 BEGIN_RING(NvCtxSurf2D, 0x184, 2);
31 OUT_RELOCo(p_region->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
32 OUT_RING (nv->channel->vram->handle);
33
34 BEGIN_RING(NvCtxSurf2D, 0x300, 4);
35 OUT_RING ((p_region->cpp == 4) ? 6 : 4);
36 OUT_RING ((nv_screen->front_pitch << 16) |
37 (p_region->pitch * p_region->cpp));
38 OUT_RELOCl(p_region->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
39 OUT_RING (nv_screen->front_offset);
40
41 for (i = 0; i < nbox; i++, pbox++) {
42 int sx, sy, dx, dy, w, h;
43
44 sx = pbox->x1 - dPriv->x;
45 sy = pbox->y1 - dPriv->y;
46 dx = pbox->x1;
47 dy = pbox->y1;
48 w = pbox->x2 - pbox->x1;
49 h = pbox->y2 - pbox->y1;
50
51 BEGIN_RING(NvImageBlit, 0x300, 3);
52 OUT_RING ((sy << 16) | sx);
53 OUT_RING ((dy << 16) | dx);
54 OUT_RING (( h << 16) | w);
55 }
56
57 FIRE_RING();
58 UNLOCK_HARDWARE(nv);
59
60 if (nv->last_stamp != dPriv->lastStamp) {
61 struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
62 st_resize_framebuffer(nvfb->stfb, dPriv->w, dPriv->h);
63 nv->last_stamp = dPriv->lastStamp;
64 }
65 }
66
67 void
68 nouveau_copy_sub_buffer(__DRIdrawablePrivate *dPriv, int x, int y, int w, int h)
69 {
70 struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
71 struct pipe_surface *surf;
72
73 surf = st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT);
74 if (surf) {
75 drm_clip_rect_t rect;
76 rect.x1 = x;
77 rect.y1 = y;
78 rect.x2 = x + w;
79 rect.y2 = y + h;
80
81 st_notify_swapbuffers(nvfb->stfb);
82 nouveau_copy_buffer(dPriv, surf, &rect);
83 }
84 }
85
86 void
87 nouveau_swap_buffers(__DRIdrawablePrivate *dPriv)
88 {
89 struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
90 struct pipe_surface *surf;
91
92 surf = st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT);
93 if (surf) {
94 st_notify_swapbuffers(nvfb->stfb);
95 nouveau_copy_buffer(dPriv, surf, NULL);
96 }
97 }
98