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