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