st/dri: Make st_framebuffer_iface the base for dri_drawable
[mesa.git] / src / gallium / state_trackers / dri / common / dri_st_api.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.9
4 *
5 * Copyright (C) 2010 LunarG Inc.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
24 *
25 * Authors:
26 * Chia-I Wu <olv@lunarg.com>
27 */
28
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "util/u_format.h"
32 #include "util/u_debug.h"
33 #include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
34
35 #include "dri_screen.h"
36 #include "dri_context.h"
37 #include "dri_drawable.h"
38 #include "dri_st_api.h"
39
40 static boolean
41 dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
42 const enum st_attachment_type *statts,
43 unsigned count,
44 struct pipe_resource **out)
45 {
46 struct dri_drawable *drawable =
47 (struct dri_drawable *) stfbi->st_manager_private;
48 struct dri_screen *screen = dri_screen(drawable->sPriv);
49 unsigned statt_mask, new_mask;
50 boolean new_stamp;
51 int i;
52
53 statt_mask = 0x0;
54 for (i = 0; i < count; i++)
55 statt_mask |= (1 << statts[i]);
56
57 /* record newly allocated textures */
58 new_mask = (statt_mask & ~drawable->texture_mask);
59
60 /*
61 * dPriv->pStamp is the server stamp. It should be accessed with a lock, at
62 * least for DRI1. dPriv->lastStamp is the client stamp. It has the value
63 * of the server stamp when last checked.
64 */
65 new_stamp = (drawable->texture_stamp != drawable->dPriv->lastStamp);
66
67 if (new_stamp || new_mask) {
68 if (new_stamp && screen->update_drawable_info)
69 screen->update_drawable_info(drawable);
70
71 screen->allocate_textures(drawable, statts, count);
72
73 /* add existing textures */
74 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
75 if (drawable->textures[i])
76 statt_mask |= (1 << i);
77 }
78
79 drawable->texture_stamp = drawable->dPriv->lastStamp;
80 drawable->texture_mask = statt_mask;
81 }
82
83 if (!out)
84 return TRUE;
85
86 for (i = 0; i < count; i++) {
87 out[i] = NULL;
88 pipe_resource_reference(&out[i], drawable->textures[statts[i]]);
89 }
90
91 return TRUE;
92 }
93
94 static boolean
95 dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
96 enum st_attachment_type statt)
97 {
98 struct dri_drawable *drawable =
99 (struct dri_drawable *) stfbi->st_manager_private;
100 struct dri_screen *screen = dri_screen(drawable->sPriv);
101
102 /* XXX remove this and just set the correct one on the framebuffer */
103 screen->flush_frontbuffer(drawable, statt);
104
105 return TRUE;
106 }
107
108 /**
109 * Init a framebuffer from the given drawable.
110 */
111 void
112 dri_init_st_framebuffer(struct dri_drawable *drawable)
113 {
114 drawable->base.visual = &drawable->stvis;
115 drawable->base.flush_front = dri_st_framebuffer_flush_front;
116 drawable->base.validate = dri_st_framebuffer_validate;
117 drawable->base.st_manager_private = (void *) drawable;
118 }
119
120 /**
121 * Destroy a framebuffer.
122 */
123 void
124 dri_close_st_framebuffer(struct dri_drawable *drawable)
125 {
126 int i;
127
128 for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
129 pipe_resource_reference(&drawable->textures[i], NULL);
130 }
131
132 /**
133 * Validate the texture at an attachment. Allocate the texture if it does not
134 * exist.
135 */
136 void
137 dri_st_framebuffer_validate_att(struct dri_drawable *drawable,
138 enum st_attachment_type statt)
139 {
140 enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
141 unsigned i, count = 0;
142
143 /* check if buffer already exists */
144 if (drawable->texture_mask & (1 << statt))
145 return;
146
147 /* make sure DRI2 does not destroy existing buffers */
148 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
149 if (drawable->texture_mask & (1 << i)) {
150 statts[count++] = i;
151 }
152 }
153 statts[count++] = statt;
154
155 drawable->texture_stamp = drawable->dPriv->lastStamp - 1;
156
157 /* this calles into the manager */
158 drawable->base.validate(&drawable->base, statts, count, NULL);
159 }
160
161 static boolean
162 dri_st_manager_get_egl_image(struct st_manager *smapi,
163 struct st_egl_image *stimg)
164 {
165 struct dri_context *ctx =
166 (struct dri_context *)stimg->stctxi->st_manager_private;
167 struct dri_screen *screen = dri_screen(ctx->sPriv);
168 __DRIimage *img = NULL;
169
170 if (screen->lookup_egl_image) {
171 img = screen->lookup_egl_image(ctx, stimg->egl_image);
172 }
173
174 if (!img)
175 return FALSE;
176
177 stimg->texture = NULL;
178 pipe_resource_reference(&stimg->texture, img->texture);
179 stimg->face = img->face;
180 stimg->level = img->level;
181 stimg->zslice = img->zslice;
182
183 return TRUE;
184 }
185
186 /**
187 * Create a state tracker manager from the given screen.
188 */
189 boolean
190 dri_init_st_manager(struct dri_screen *screen)
191 {
192 screen->base.screen = screen->pipe_screen;
193 screen->base.get_egl_image = dri_st_manager_get_egl_image;
194 screen->st_api = st_gl_api_create();
195
196 if (!screen->st_api)
197 return FALSE;
198
199 return TRUE;
200 }
201
202 void
203 dri_close_st_manager(struct dri_screen *screen)
204 {
205 if (screen->st_api && screen->st_api->destroy)
206 screen->st_api->destroy(screen->st_api);
207 }