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