1/*
2 * Copyright 2006-2008, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Philippe Houdoin, philippe.houdoin@free.fr
7 */
8/*
9 * Mesa 3-D graphics library
10 * Version:  6.1
11 *
12 * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
13 */
14
15#include "FakeRenderer.h"
16
17#include <stdio.h>
18
19#include <Autolock.h>
20#include <DirectWindowPrivate.h>
21#include <GraphicsDefs.h>
22#include <Screen.h>
23
24
25extern const char * color_space_name(color_space space);
26
27
28extern "C" _EXPORT BGLRenderer*
29instantiate_gl_renderer(BGLView* view, ulong options,
30	BGLDispatcher* dispatcher)
31{
32	return new FakeRenderer(view, options, dispatcher);
33}
34
35
36FakeRenderer::FakeRenderer(BGLView* view, ulong options,
37		BGLDispatcher* dispatcher)
38	: BGLRenderer(view, options, dispatcher),
39	fOptions(options),
40	fDrawLocker("direct draw locker"),
41	fFrameBuffer(NULL),
42	fColorSpace(B_NO_COLOR_SPACE),
43	fRects(NULL),
44	fConnected(false),
45	fDisabled(false)
46{
47	fDrawSem = create_sem(0, "FakeRenderer draw");
48	fDrawThread = spawn_thread(_DirectDrawThread, "FakeRenderer direct draw", B_DISPLAY_PRIORITY, this);
49	resume_thread(fDrawThread);
50
51}
52
53FakeRenderer::~FakeRenderer()
54{
55	// Wakeup the draw thread by murdering its favorite semaphore
56	delete_sem(fDrawSem);
57
58	status_t exit_value;
59	wait_for_thread(fDrawThread, &exit_value);
60
61	free(fRects);
62}
63
64
65void
66FakeRenderer::SwapBuffers(bool VSync)
67{
68	if (VSync && GLView()->Window()) {
69		// TODO: find a way to check VSync support is actually working...
70		BScreen screen(GLView()->Window());
71		screen.WaitForRetrace();
72	}
73
74	// Simulate rendering a new buffer: randomized buffer color ;-)
75	fDrawColor = make_color(rand() % 0xFF, rand() % 0xFF, rand() % 0xFF);
76
77	if (!fConnected || fDisabled) {
78		GLView()->LockLooper();
79		// TODO : refresh area
80		GLView()->UnlockLooper();
81		return;
82	}
83
84	// Direct mode: wake up drawing thread
85	release_sem(fDrawSem);
86}
87
88
89void
90FakeRenderer::Draw(BRect updateRect)
91{
92/*
93	if (fBitmap && (!fDirectModeEnabled || (fInfo == NULL)))
94		GLView()->DrawBitmap(fBitmap, updateRect, updateRect);
95*/
96}
97
98
99void
100FakeRenderer::EnableDirectMode(bool enabled)
101{
102	fDisabled = ! enabled;
103}
104
105
106void
107FakeRenderer::DirectConnected(direct_buffer_info *info)
108{
109	if (!fConnected && fDisabled)
110		return;
111
112	BAutolock lock(fDrawLocker);
113
114	switch (info->buffer_state & B_DIRECT_MODE_MASK) {
115	case B_DIRECT_START:
116		fConnected = true;
117		/* fall through */
118	case B_DIRECT_MODIFY:
119		fFrameBuffer = (uint8 *) info->bits;
120		fBytesPerRow = info->bytes_per_row;
121		fColorSpace = info->pixel_format;
122
123		free(fRects);
124		fRectsCount = info->clip_list_count;
125		fRects = (clipping_rect *) malloc(fRectsCount * sizeof(clipping_rect));
126		memcpy(fRects, info->clip_list, fRectsCount * sizeof(clipping_rect));
127
128		fprintf(stderr, "fFrameBuffer = %p\n"
129						"fBytesPerRow = %d\n"
130						"fColorSpace  = %s\n", fFrameBuffer, fBytesPerRow, color_space_name(fColorSpace));
131		for (int i = 0; i < fRectsCount; i++) {
132			fprintf(stderr, "fRects[%d] = %d, %d to %d, %d\n",
133				i, fRects[i].left, fRects[i].top, fRects[i].right, fRects[i].bottom);
134		}
135		break;
136
137	case B_DIRECT_STOP:
138		fConnected = false;
139		break;
140	}
141
142	fprintf(stderr, "fConnected = %s\n", fConnected ? "true" : "false");
143}
144
145
146// ----
147
148
149int32
150FakeRenderer::_DirectDrawThread(void *data)
151{
152	FakeRenderer *me = (FakeRenderer *) data;
153	return me->_DirectDrawThread();
154}
155
156
157int32
158FakeRenderer::_DirectDrawThread(void)
159{
160	// Let's wait forever/until semaphore death next redraw
161	while (acquire_sem(fDrawSem) == B_OK) {
162
163		BAutolock lock(fDrawLocker);
164
165		int i;
166		int32 x, y;
167
168		switch(fColorSpace) {
169		case B_RGB32:
170		case B_RGBA32:
171			for (i = 0; i < fRectsCount; i++) {
172				for (y = fRects[i].top; y <= fRects[i].bottom; y++) {
173					uint8 * p = fFrameBuffer + ( y * fBytesPerRow ) + fRects[i].left * 4;
174					for (x = fRects[i].left; x <= fRects[i].right; x++) {
175						*p++ = fDrawColor.blue;
176						*p++ = fDrawColor.green;
177						*p++ = fDrawColor.red;
178						*p++ = fDrawColor.alpha;
179					}
180				}
181			}
182			break;
183
184		case B_RGB24:
185		case B_RGB32_BIG:
186		case B_RGBA32_BIG:
187		case B_RGB24_BIG:
188			/* fill this in with the color-space conversion
189			 * code of your choosing
190			 */
191			break;
192
193		case B_RGB16:
194		case B_RGB15:
195		case B_RGBA15:
196		case B_RGB16_BIG:
197		case B_RGB15_BIG:
198		case B_RGBA15_BIG:
199			/* same here */
200			break;
201
202		case B_CMAP8:
203			/* same here */
204			break;
205
206		default:
207			/* unsupported mode */
208			break;
209		}
210
211	} // while draw
212
213	return 0;
214}
215
216
217
218