b75dc26bc39ed939e1d87331c5b5ef5e4da39767
[mesa.git] / src / gallium / state_trackers / hgl / hgl.c
1 /*
2 * Copyright 2012-2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Artur Wyszynski, harakash@gmail.com
7 * Alexander von Gluck IV, kallisti5@unixzen.com
8 */
9
10
11 #include "GLView.h"
12
13 #include "pipe/p_format.h"
14 #include "util/u_atomic.h"
15 #include "util/u_format.h"
16 #include "util/u_memory.h"
17 #include "util/u_inlines.h"
18
19 #include "hgl_context.h"
20
21
22 #ifdef DEBUG
23 # define TRACE(x...) printf("hgl:state_tracker: " x)
24 # define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
25 #else
26 # define TRACE(x...)
27 # define CALLED()
28 #endif
29 #define ERROR(x...) printf("hgl:state_tracker: " x)
30
31
32 // Perform a safe void to hgl_context cast
33 static INLINE struct hgl_context*
34 hgl_st_context(struct st_context_iface *stctxi)
35 {
36 struct hgl_context* context;
37 assert(stctxi);
38 context = (struct hgl_context*)stctxi->st_manager_private;
39 assert(context);
40 return context;
41 }
42
43
44 // Perform a safe void to hgl_buffer cast
45 static INLINE struct hgl_buffer*
46 hgl_st_framebuffer(struct st_framebuffer_iface *stfbi)
47 {
48 struct hgl_buffer* buffer;
49 assert(stfbi);
50 buffer = (struct hgl_buffer*)stfbi->st_manager_private;
51 assert(buffer);
52 return buffer;
53 }
54
55
56 static boolean
57 hgl_st_framebuffer_flush_front(struct st_context_iface *stctxi,
58 struct st_framebuffer_iface* stfbi, enum st_attachment_type statt)
59 {
60 CALLED();
61
62 //struct hgl_context* context = hgl_st_context(stctxi);
63 //struct hgl_buffer* buffer = hgl_st_context(stfbi);
64
65 #if 0
66 struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
67 pipe_mutex_lock(stwfb->fb->mutex);
68
69 struct pipe_resource* resource = textures[statt];
70 if (resource)
71 stw_framebuffer_present_locked(...);
72 #endif
73
74 return TRUE;
75 }
76
77
78 static boolean
79 hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
80 unsigned width, unsigned height, unsigned mask)
81 {
82 struct hgl_buffer* buffer;
83 enum st_attachment_type i;
84 struct pipe_resource templat;
85
86 CALLED();
87
88 buffer = hgl_st_framebuffer(stfbi);
89
90 if (buffer->width != width || buffer->height != height) {
91 for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
92 pipe_resource_reference(&buffer->textures[i], NULL);
93 }
94
95 memset(&templat, 0, sizeof(templat));
96 templat.target = buffer->target;
97 templat.width0 = width;
98 templat.height0 = height;
99 templat.depth0 = 1;
100 templat.array_size = 1;
101 templat.last_level = 0;
102
103 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
104 enum pipe_format format;
105 unsigned bind;
106
107 switch (i) {
108 case ST_ATTACHMENT_FRONT_LEFT:
109 case ST_ATTACHMENT_BACK_LEFT:
110 case ST_ATTACHMENT_FRONT_RIGHT:
111 case ST_ATTACHMENT_BACK_RIGHT:
112 format = buffer->visual->color_format;
113 bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;
114 break;
115 case ST_ATTACHMENT_DEPTH_STENCIL:
116 format = buffer->visual->depth_stencil_format;
117 bind = PIPE_BIND_DEPTH_STENCIL;
118 break;
119 default:
120 format = PIPE_FORMAT_NONE;
121 bind = 0;
122 break;
123 }
124
125 if (format != PIPE_FORMAT_NONE) {
126 templat.format = format;
127 templat.bind = bind;
128 buffer->textures[i] = buffer->screen->resource_create(buffer->screen,
129 &templat);
130 if (!buffer->textures[i])
131 return FALSE;
132 }
133 }
134
135 buffer->width = width;
136 buffer->height = height;
137 buffer->mask = mask;
138
139 return TRUE;
140 }
141
142
143 /**
144 * Called by the st manager to validate the framebuffer (allocate
145 * its resources).
146 */
147 static boolean
148 hgl_st_framebuffer_validate(struct st_context_iface *stctxi,
149 struct st_framebuffer_iface *stfbi, const enum st_attachment_type *statts,
150 unsigned count, struct pipe_resource **out)
151 {
152 struct hgl_context* context;
153 struct hgl_buffer* buffer;
154 unsigned stAttachmentMask, newMask;
155 unsigned i;
156 boolean resized;
157
158 CALLED();
159
160 context = hgl_st_context(stctxi);
161 buffer = hgl_st_framebuffer(stfbi);
162
163 //int32 width = 0;
164 //int32 height = 0;
165 //get_bitmap_size(context->bitmap, &width, &height);
166
167 // Build mask of current attachments
168 stAttachmentMask = 0;
169 for (i = 0; i < count; i++)
170 stAttachmentMask |= 1 << statts[i];
171
172 newMask = stAttachmentMask & ~buffer->mask;
173
174 resized = (buffer->width != context->width)
175 || (buffer->height != context->height);
176
177 if (resized || newMask) {
178 boolean ret;
179 TRACE("%s: resize event. old: %d x %d; new: %d x %d\n", __func__,
180 buffer->width, buffer->height, context->width, context->height);
181
182 ret = hgl_st_framebuffer_validate_textures(stfbi,
183 context->width, context->height, stAttachmentMask);
184
185 if (!ret)
186 return ret;
187
188 // TODO: Simply update attachments
189 //if (!resized) {
190
191 //}
192 }
193
194 for (i = 0; i < count; i++) {
195 out[i] = NULL;
196 pipe_resource_reference(&out[i], buffer->textures[statts[i]]);
197 }
198
199 return TRUE;
200 }
201
202
203 static int
204 hgl_st_manager_get_param(struct st_manager *smapi, enum st_manager_param param)
205 {
206 CALLED();
207
208 switch (param) {
209 case ST_MANAGER_BROKEN_INVALIDATE:
210 return 1;
211 }
212
213 return 0;
214 }
215
216
217 /**
218 * Create new framebuffer
219 */
220 struct hgl_buffer *
221 hgl_create_st_framebuffer(struct hgl_context* context)
222 {
223 struct hgl_buffer *buffer;
224 CALLED();
225
226 // Our requires before creating a framebuffer
227 assert(context);
228 assert(context->screen);
229 assert(context->stVisual);
230
231 buffer = CALLOC_STRUCT(hgl_buffer);
232 assert(buffer);
233
234 // calloc and configure our st_framebuffer interface
235 buffer->stfbi = CALLOC_STRUCT(st_framebuffer_iface);
236 assert(buffer->stfbi);
237
238 // Prepare our buffer
239 buffer->visual = context->stVisual;
240 buffer->screen = context->screen;
241
242 if (context->screen->get_param(buffer->screen, PIPE_CAP_NPOT_TEXTURES))
243 buffer->target = PIPE_TEXTURE_2D;
244 else
245 buffer->target = PIPE_TEXTURE_RECT;
246
247 // Prepare our state_tracker interface
248 buffer->stfbi->flush_front = hgl_st_framebuffer_flush_front;
249 buffer->stfbi->validate = hgl_st_framebuffer_validate;
250 buffer->stfbi->visual = context->stVisual;
251
252 p_atomic_set(&buffer->stfbi->stamp, 1);
253 buffer->stfbi->st_manager_private = (void*)buffer;
254
255 return buffer;
256 }
257
258
259 struct st_manager *
260 hgl_create_st_manager(struct hgl_context* context)
261 {
262 struct st_manager* manager;
263
264 CALLED();
265
266 // Required things
267 assert(context);
268 assert(context->screen);
269
270 manager = CALLOC_STRUCT(st_manager);
271 assert(manager);
272
273 //manager->display = dpy;
274 manager->screen = context->screen;
275 manager->get_param = hgl_st_manager_get_param;
276
277 return manager;
278 }
279
280
281 void
282 hgl_destroy_st_manager(struct st_manager *manager)
283 {
284 CALLED();
285
286 FREE(manager);
287 }
288
289
290 struct st_visual*
291 hgl_create_st_visual(ulong options)
292 {
293 struct st_visual* visual;
294
295 CALLED();
296
297 visual = CALLOC_STRUCT(st_visual);
298 assert(visual);
299
300 // Determine color format
301 if ((options & BGL_INDEX) != 0) {
302 // Index color
303 visual->color_format = PIPE_FORMAT_B5G6R5_UNORM;
304 // TODO: Indexed color depth buffer?
305 visual->depth_stencil_format = PIPE_FORMAT_NONE;
306 } else {
307 // RGB color
308 visual->color_format = (options & BGL_ALPHA)
309 ? PIPE_FORMAT_BGRA8888_UNORM : PIPE_FORMAT_BGRX8888_UNORM;
310 // TODO: Determine additional stencil formats
311 visual->depth_stencil_format = (options & BGL_DEPTH)
312 ? PIPE_FORMAT_Z24_UNORM_S8_UINT : PIPE_FORMAT_NONE;
313 }
314
315 visual->accum_format = (options & BGL_ACCUM)
316 ? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
317
318 visual->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
319 visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
320
321 if ((options & BGL_DOUBLE) != 0) {
322 visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
323 visual->render_buffer = ST_ATTACHMENT_BACK_LEFT;
324 }
325
326 #if 0
327 if ((options & BGL_STEREO) != 0) {
328 visual->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
329 if ((options & BGL_DOUBLE) != 0)
330 visual->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
331 }
332 #endif
333
334 if ((options & BGL_DEPTH) || (options & BGL_STENCIL))
335 visual->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
336
337 TRACE("%s: Visual color format: %s\n", __func__,
338 util_format_name(visual->color_format));
339
340 return visual;
341 }
342
343
344 void
345 hgl_destroy_st_visual(struct st_visual* visual)
346 {
347 CALLED();
348
349 FREE(visual);
350 }