2 * Copyright 2006-2012, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Jérôme Duval, korli@users.berlios.de
7 * Philippe Houdoin, philippe.houdoin@free.fr
8 * Artur Wyszynski, harakash@gmail.com
9 * Alexander von Gluck IV, kallisti5@unixzen.com
13 #include "SoftwareRenderer.h"
16 #include <interface/DirectWindowPrivate.h>
17 #include <GraphicsDefs.h>
25 # define TRACE(x...) printf("SoftwareRenderer: " x)
26 # define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
31 #define ERROR(x...) printf("SoftwareRenderer: " x)
34 extern const char* color_space_name(color_space space
);
37 extern "C" _EXPORT BGLRenderer
*
38 instantiate_gl_renderer(BGLView
*view
, ulong opts
, BGLDispatcher
*dispatcher
)
40 return new SoftwareRenderer(view
, opts
, dispatcher
);
43 SoftwareRenderer::SoftwareRenderer(BGLView
*view
, ulong options
,
44 BGLDispatcher
* dispatcher
)
46 BGLRenderer(view
, options
, dispatcher
),
48 fDirectModeEnabled(false),
50 fInfoLocker("info locker"),
52 fColorSpace(B_NO_COLOR_SPACE
)
56 // Disable double buffer for the moment.
57 options
&= ~BGL_DOUBLE
;
59 // Initialize the "Haiku Software GL Pipe"
63 fContextObj
= new GalliumContext(options
);
65 TRACE("Haiku Software GL Pipe initialization time: %f.\n",
69 BRect b
= view
->Bounds();
70 fColorSpace
= BScreen(view
->Window()).ColorSpace();
71 TRACE("%s: Colorspace:\t%s\n", __func__
, color_space_name(fColorSpace
));
73 fWidth
= (GLint
)b
.IntegerWidth();
74 fHeight
= (GLint
)b
.IntegerHeight();
80 // Initialize the first "Haiku Software GL Pipe" context
82 fContextID
= fContextObj
->CreateContext(fBitmap
);
86 ERROR("%s: There was an error creating the context!\n", __func__
);
88 TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",
89 __func__
, difftime(end
, beg
));
92 if (!fContextObj
->GetCurrentContext())
97 SoftwareRenderer::~SoftwareRenderer()
109 SoftwareRenderer::LockGL()
112 BGLRenderer::LockGL();
114 color_space cs
= BScreen(GLView()->Window()).ColorSpace();
116 BAutolock
lock(fInfoLocker
);
117 if (fDirectModeEnabled
&& fInfo
!= NULL
) {
118 fNewWidth
= fInfo
->window_bounds
.right
- fInfo
->window_bounds
.left
;
119 fNewHeight
= fInfo
->window_bounds
.bottom
- fInfo
->window_bounds
.top
;
122 if (fBitmap
&& cs
== fColorSpace
&& fNewWidth
== fWidth
123 && fNewHeight
== fHeight
) {
124 fContextObj
->SetCurrentContext(fBitmap
, fContextID
);
130 fHeight
= fNewHeight
;
133 fContextObj
->SetCurrentContext(fBitmap
, fContextID
);
138 SoftwareRenderer::UnlockGL()
141 if ((fOptions
& BGL_DOUBLE
) == 0) {
144 fContextObj
->SetCurrentContext(NULL
, fContextID
);
145 BGLRenderer::UnlockGL();
150 SoftwareRenderer::SwapBuffers(bool vsync
)
156 BScreen
screen(GLView()->Window());
158 fContextObj
->SwapBuffers(fContextID
);
160 BAutolock
lock(fInfoLocker
);
162 if (!fDirectModeEnabled
|| fInfo
== NULL
) {
163 if (GLView()->LockLooperWithTimeout(1000) == B_OK
) {
164 GLView()->DrawBitmap(fBitmap
, B_ORIGIN
);
165 GLView()->UnlockLooper();
167 screen
.WaitForRetrace();
172 // check the bitmap size still matches the size
173 if (fInfo
->window_bounds
.bottom
- fInfo
->window_bounds
.top
174 != fBitmap
->Bounds().IntegerHeight()
175 || fInfo
->window_bounds
.right
- fInfo
->window_bounds
.left
176 != fBitmap
->Bounds().IntegerWidth()) {
177 ERROR("%s: Bitmap size doesn't match size!\n", __func__
);
181 uint32 bytesPerRow
= fBitmap
->BytesPerRow();
182 uint8 bytesPerPixel
= bytesPerRow
/ fBitmap
->Bounds().IntegerWidth();
184 for (uint32 i
= 0; i
< fInfo
->clip_list_count
; i
++) {
185 clipping_rect
*clip
= &fInfo
->clip_list
[i
];
186 int32 height
= clip
->bottom
- clip
->top
+ 1;
188 = (clip
->right
- clip
->left
+ 1) * bytesPerPixel
;
189 bytesWidth
-= bytesPerPixel
;
190 uint8
*p
= (uint8
*)fInfo
->bits
+ clip
->top
191 * fInfo
->bytes_per_row
+ clip
->left
* bytesPerPixel
;
192 uint8
*b
= (uint8
*)fBitmap
->Bits()
193 + (clip
->top
- fInfo
->window_bounds
.top
) * bytesPerRow
194 + (clip
->left
- fInfo
->window_bounds
.left
) * bytesPerPixel
;
196 for (int y
= 0; y
< height
- 1; y
++) {
197 memcpy(p
, b
, bytesWidth
);
198 p
+= fInfo
->bytes_per_row
;
204 screen
.WaitForRetrace();
209 SoftwareRenderer::Draw(BRect updateRect
)
212 if ((!fDirectModeEnabled
|| fInfo
== NULL
) && fBitmap
)
213 GLView()->DrawBitmap(fBitmap
, updateRect
, updateRect
);
218 SoftwareRenderer::CopyPixelsOut(BPoint location
, BBitmap
*bitmap
)
221 color_space scs
= fBitmap
->ColorSpace();
222 color_space dcs
= bitmap
->ColorSpace();
224 if (scs
!= dcs
&& (scs
!= B_RGBA32
|| dcs
!= B_RGB32
)) {
225 ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n",
226 __PRETTY_FUNCTION__
, color_space_name(scs
), color_space_name(dcs
));
230 BRect sr
= fBitmap
->Bounds();
231 BRect dr
= bitmap
->Bounds();
233 // int32 w1 = sr.IntegerWidth();
234 // int32 h1 = sr.IntegerHeight();
235 // int32 w2 = dr.IntegerWidth();
236 // int32 h2 = dr.IntegerHeight();
238 sr
= sr
& dr
.OffsetBySelf(location
);
239 dr
= sr
.OffsetByCopy(-location
.x
, -location
.y
);
241 uint8
*ps
= (uint8
*) fBitmap
->Bits();
242 uint8
*pd
= (uint8
*) bitmap
->Bits();
245 for (y
= (uint32
) sr
.top
; y
<= (uint32
) sr
.bottom
; y
++) {
246 s
= (uint32
*)(ps
+ y
* fBitmap
->BytesPerRow());
247 s
+= (uint32
) sr
.left
;
249 d
= (uint32
*)(pd
+ (y
+ (uint32
)(dr
.top
- sr
.top
))
250 * bitmap
->BytesPerRow());
251 d
+= (uint32
) dr
.left
;
252 memcpy(d
, s
, dr
.IntegerWidth() * 4);
260 SoftwareRenderer::CopyPixelsIn(BBitmap
*bitmap
, BPoint location
)
264 color_space sourceCS
= bitmap
->ColorSpace();
265 color_space destinationCS
= fBitmap
->ColorSpace();
267 if (sourceCS
!= destinationCS
268 && (sourceCS
!= B_RGB32
|| destinationCS
!= B_RGBA32
)) {
269 ERROR("%s::CopyPixelsIn(): incompatible color space: %s != %s\n",
270 __PRETTY_FUNCTION__
, color_space_name(sourceCS
),
271 color_space_name(destinationCS
));
275 BRect sr
= bitmap
->Bounds();
276 BRect dr
= fBitmap
->Bounds();
278 sr
= sr
& dr
.OffsetBySelf(location
);
279 dr
= sr
.OffsetByCopy(-location
.x
, -location
.y
);
281 uint8
*ps
= (uint8
*) bitmap
->Bits();
282 uint8
*pd
= (uint8
*) fBitmap
->Bits();
286 for (y
= (uint32
) sr
.top
; y
<= (uint32
) sr
.bottom
; y
++) {
287 s
= (uint32
*)(ps
+ y
* bitmap
->BytesPerRow());
288 s
+= (uint32
) sr
.left
;
290 d
= (uint32
*)(pd
+ (y
+ (uint32
)(dr
.top
- sr
.top
))
291 * fBitmap
->BytesPerRow());
292 d
+= (uint32
) dr
.left
;
294 memcpy(d
, s
, dr
.IntegerWidth() * 4);
302 SoftwareRenderer::EnableDirectMode(bool enabled
)
304 fDirectModeEnabled
= enabled
;
309 SoftwareRenderer::DirectConnected(direct_buffer_info
*info
)
312 BAutolock
lock(fInfoLocker
);
315 fInfo
= (direct_buffer_info
*)calloc(1,
316 DIRECT_BUFFER_INFO_AREA_SIZE
);
318 memcpy(fInfo
, info
, DIRECT_BUFFER_INFO_AREA_SIZE
);
327 SoftwareRenderer::FrameResized(float width
, float height
)
329 TRACE("%s: %f x %f\n", __func__
, width
, height
);
331 BAutolock
lock(fInfoLocker
);
332 fNewWidth
= (GLuint
)width
;
333 fNewHeight
= (GLuint
)height
;
338 SoftwareRenderer::_AllocateBitmap()
342 // allocate new size of back buffer bitmap
343 BAutolock
lock(fInfoLocker
);
346 if (fWidth
< 1 || fHeight
< 1) {
347 TRACE("%s: Can't allocate bitmap of %dx%d\n", __func__
,
351 BRect
rect(0.0, 0.0, fWidth
, fHeight
);
352 fBitmap
= new (std::nothrow
) BBitmap(rect
, fColorSpace
);
353 if (fBitmap
== NULL
) {
354 TRACE("%s: Can't create bitmap!\n", __func__
);
358 TRACE("%s: New bitmap size: %ld x %ld\n", __func__
,
359 fBitmap
->Bounds().IntegerWidth(), fBitmap
->Bounds().IntegerHeight());
361 fContextObj
->ResizeViewport(fWidth
, fHeight
);
365 void *data
= fBitmap
->Bits();
366 memset(data
, 0xcc, fBitmap
->BitsLength());