aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c
blob: 450c981ca44f60161ec7b67d861cdcb5c803dedd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <main/glheader.h>
#include <glapi/glthread.h>
#include <GL/internal/glcore.h>

#include <pipe/p_context.h>
#include <state_tracker/st_public.h>
#include <state_tracker/st_context.h>
#include <state_tracker/st_cb_fbo.h>

#include "../common/nouveau_local.h"
#include "nouveau_context_dri.h"
#include "nouveau_screen_dri.h"
#include "nouveau_swapbuffers.h"

void
nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
		    const drm_clip_rect_t *rect)
{
	struct nouveau_context_dri *nv = dPriv->driContextPriv->driverPrivate;
	drm_clip_rect_t *pbox;
	int nbox, i;

	LOCK_HARDWARE(&nv->base);
	if (!dPriv->numClipRects) {
		UNLOCK_HARDWARE(&nv->base);
		return;
	}
	pbox = dPriv->pClipRects;
	nbox = dPriv->numClipRects;

	if (nv->base.surface_copy_prep) {
		nv->base.surface_copy_prep(&nv->base, nv->base.frontbuffer, surf);
		for (i = 0; i < nbox; i++, pbox++) {
			int sx, sy, dx, dy, w, h;

			sx = pbox->x1 - dPriv->x;
			sy = pbox->y1 - dPriv->y;
			dx = pbox->x1;
			dy = pbox->y1;
			w  = pbox->x2 - pbox->x1;
			h  = pbox->y2 - pbox->y1;

			nv->base.surface_copy(&nv->base, dx, dy, sx, sy, w, h);
		}
	} else {
		struct pipe_context *pipe = nv->base.nvc->pctx[nv->base.pctx_id];

		for (i = 0; i < nbox; i++, pbox++) {
			int sx, sy, dx, dy, w, h;

			sx = pbox->x1 - dPriv->x;
			sy = pbox->y1 - dPriv->y;
			dx = pbox->x1;
			dy = pbox->y1;
			w  = pbox->x2 - pbox->x1;
			h  = pbox->y2 - pbox->y1;

			pipe->surface_copy(pipe, FALSE, nv->base.frontbuffer,
					   dx, dy, surf, sx, sy, w, h);
		}
	}

	FIRE_RING(nv->base.nvc->channel);
	UNLOCK_HARDWARE(&nv->base);

	if (nv->last_stamp != dPriv->lastStamp) {
		struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
		st_resize_framebuffer(nvfb->stfb, dPriv->w, dPriv->h);
		nv->last_stamp = dPriv->lastStamp;
	}
}

void
nouveau_copy_sub_buffer(__DRIdrawablePrivate *dPriv, int x, int y, int w, int h)
{
	struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
	struct pipe_surface *surf;

	st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT, &surf);
	if (surf) {
		drm_clip_rect_t rect;
		rect.x1 = x;
		rect.y1 = y;
		rect.x2 = x + w;
		rect.y2 = y + h;

		st_notify_swapbuffers(nvfb->stfb);
		nouveau_copy_buffer(dPriv, surf, &rect);
	}
}

void
nouveau_swap_buffers(__DRIdrawablePrivate *dPriv)
{
	struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
	struct pipe_surface *surf;

	st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT, &surf);
	if (surf) {
		st_notify_swapbuffers(nvfb->stfb);
		nouveau_copy_buffer(dPriv, surf, NULL);
	}
}

void
nouveau_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surf,
			  void *context_private)
{
	struct nouveau_context_dri *nv = context_private;
	__DRIdrawablePrivate *dPriv = nv->dri_drawable;

	nouveau_copy_buffer(dPriv, surf, NULL);
}

void
nouveau_contended_lock(struct nouveau_context *nv)
{
	struct nouveau_context_dri *nv_sub = (struct nouveau_context_dri*)nv;
	__DRIdrawablePrivate *dPriv = nv_sub->dri_drawable;
	__DRIscreenPrivate *sPriv = nv_sub->dri_screen;

	/* If the window moved, may need to set a new cliprect now.
	 *
	 * NOTE: This releases and regains the hw lock, so all state
	 * checking must be done *after* this call:
	 */
	if (dPriv)
		DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
}