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();
78 // Initialize the first "Haiku Software GL Pipe" context
80 fContextID
= fContextObj
->CreateContext(fBitmap
);
84 ERROR("%s: There was an error creating the context!\n", __func__
);
86 TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",
87 __func__
, difftime(end
, beg
));
90 if (!fContextObj
->GetCurrentContext())
95 SoftwareRenderer::~SoftwareRenderer()
107 SoftwareRenderer::LockGL()
110 BGLRenderer::LockGL();
112 color_space cs
= BScreen(GLView()->Window()).ColorSpace();
114 BAutolock
lock(fInfoLocker
);
115 if (fDirectModeEnabled
&& fInfo
!= NULL
) {
116 fWidth
= fInfo
->window_bounds
.right
- fInfo
->window_bounds
.left
;
117 fHeight
= fInfo
->window_bounds
.bottom
- fInfo
->window_bounds
.top
;
120 if (fBitmap
&& cs
== fColorSpace
&& fContextObj
->Validate(fWidth
, fHeight
)) {
121 fContextObj
->SetCurrentContext(fBitmap
, fContextID
);
128 fContextObj
->SetCurrentContext(fBitmap
, fContextID
);
133 SoftwareRenderer::UnlockGL()
136 if ((fOptions
& BGL_DOUBLE
) == 0) {
139 fContextObj
->SetCurrentContext(NULL
, fContextID
);
140 BGLRenderer::UnlockGL();
145 SoftwareRenderer::SwapBuffers(bool vsync
)
151 BScreen
screen(GLView()->Window());
153 fContextObj
->SwapBuffers(fContextID
);
155 BAutolock
lock(fInfoLocker
);
157 if (!fDirectModeEnabled
|| fInfo
== NULL
) {
158 if (GLView()->LockLooperWithTimeout(1000) == B_OK
) {
159 GLView()->DrawBitmap(fBitmap
, B_ORIGIN
);
160 GLView()->UnlockLooper();
162 screen
.WaitForRetrace();
167 // check the bitmap size still matches the size
168 if (fInfo
->window_bounds
.bottom
- fInfo
->window_bounds
.top
169 != fBitmap
->Bounds().IntegerHeight()
170 || fInfo
->window_bounds
.right
- fInfo
->window_bounds
.left
171 != fBitmap
->Bounds().IntegerWidth()) {
172 ERROR("%s: Bitmap size doesn't match size!\n", __func__
);
176 uint32 bytesPerRow
= fBitmap
->BytesPerRow();
177 uint8 bytesPerPixel
= bytesPerRow
/ fBitmap
->Bounds().IntegerWidth();
179 for (uint32 i
= 0; i
< fInfo
->clip_list_count
; i
++) {
180 clipping_rect
*clip
= &fInfo
->clip_list
[i
];
181 int32 height
= clip
->bottom
- clip
->top
+ 1;
183 = (clip
->right
- clip
->left
+ 1) * bytesPerPixel
;
184 bytesWidth
-= bytesPerPixel
;
185 uint8
*p
= (uint8
*)fInfo
->bits
+ clip
->top
186 * fInfo
->bytes_per_row
+ clip
->left
* bytesPerPixel
;
187 uint8
*b
= (uint8
*)fBitmap
->Bits()
188 + (clip
->top
- fInfo
->window_bounds
.top
) * bytesPerRow
189 + (clip
->left
- fInfo
->window_bounds
.left
) * bytesPerPixel
;
191 for (int y
= 0; y
< height
- 1; y
++) {
192 memcpy(p
, b
, bytesWidth
);
193 p
+= fInfo
->bytes_per_row
;
199 screen
.WaitForRetrace();
204 SoftwareRenderer::Draw(BRect updateRect
)
207 if ((!fDirectModeEnabled
|| fInfo
== NULL
) && fBitmap
)
208 GLView()->DrawBitmap(fBitmap
, updateRect
, updateRect
);
213 SoftwareRenderer::CopyPixelsOut(BPoint location
, BBitmap
*bitmap
)
216 color_space scs
= fBitmap
->ColorSpace();
217 color_space dcs
= bitmap
->ColorSpace();
219 if (scs
!= dcs
&& (scs
!= B_RGBA32
|| dcs
!= B_RGB32
)) {
220 ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n",
221 __PRETTY_FUNCTION__
, color_space_name(scs
), color_space_name(dcs
));
225 BRect sr
= fBitmap
->Bounds();
226 BRect dr
= bitmap
->Bounds();
228 // int32 w1 = sr.IntegerWidth();
229 // int32 h1 = sr.IntegerHeight();
230 // int32 w2 = dr.IntegerWidth();
231 // int32 h2 = dr.IntegerHeight();
233 sr
= sr
& dr
.OffsetBySelf(location
);
234 dr
= sr
.OffsetByCopy(-location
.x
, -location
.y
);
236 uint8
*ps
= (uint8
*) fBitmap
->Bits();
237 uint8
*pd
= (uint8
*) bitmap
->Bits();
240 for (y
= (uint32
) sr
.top
; y
<= (uint32
) sr
.bottom
; y
++) {
241 s
= (uint32
*)(ps
+ y
* fBitmap
->BytesPerRow());
242 s
+= (uint32
) sr
.left
;
244 d
= (uint32
*)(pd
+ (y
+ (uint32
)(dr
.top
- sr
.top
))
245 * bitmap
->BytesPerRow());
246 d
+= (uint32
) dr
.left
;
247 memcpy(d
, s
, dr
.IntegerWidth() * 4);
255 SoftwareRenderer::CopyPixelsIn(BBitmap
*bitmap
, BPoint location
)
259 color_space sourceCS
= bitmap
->ColorSpace();
260 color_space destinationCS
= fBitmap
->ColorSpace();
262 if (sourceCS
!= destinationCS
263 && (sourceCS
!= B_RGB32
|| destinationCS
!= B_RGBA32
)) {
264 ERROR("%s::CopyPixelsIn(): incompatible color space: %s != %s\n",
265 __PRETTY_FUNCTION__
, color_space_name(sourceCS
),
266 color_space_name(destinationCS
));
270 BRect sr
= bitmap
->Bounds();
271 BRect dr
= fBitmap
->Bounds();
273 sr
= sr
& dr
.OffsetBySelf(location
);
274 dr
= sr
.OffsetByCopy(-location
.x
, -location
.y
);
276 uint8
*ps
= (uint8
*) bitmap
->Bits();
277 uint8
*pd
= (uint8
*) fBitmap
->Bits();
281 for (y
= (uint32
) sr
.top
; y
<= (uint32
) sr
.bottom
; y
++) {
282 s
= (uint32
*)(ps
+ y
* bitmap
->BytesPerRow());
283 s
+= (uint32
) sr
.left
;
285 d
= (uint32
*)(pd
+ (y
+ (uint32
)(dr
.top
- sr
.top
))
286 * fBitmap
->BytesPerRow());
287 d
+= (uint32
) dr
.left
;
289 memcpy(d
, s
, dr
.IntegerWidth() * 4);
297 SoftwareRenderer::EnableDirectMode(bool enabled
)
299 fDirectModeEnabled
= enabled
;
304 SoftwareRenderer::DirectConnected(direct_buffer_info
*info
)
307 BAutolock
lock(fInfoLocker
);
310 fInfo
= (direct_buffer_info
*)calloc(1,
311 DIRECT_BUFFER_INFO_AREA_SIZE
);
313 memcpy(fInfo
, info
, DIRECT_BUFFER_INFO_AREA_SIZE
);
322 SoftwareRenderer::FrameResized(float width
, float height
)
324 TRACE("%s: %f x %f\n", __func__
, width
, height
);
326 BAutolock
lock(fInfoLocker
);
327 fWidth
= (GLuint
)width
;
328 fHeight
= (GLuint
)height
;
333 SoftwareRenderer::_AllocateBitmap()
337 // allocate new size of back buffer bitmap
338 BAutolock
lock(fInfoLocker
);
342 if (fWidth
< 1 || fHeight
< 1) {
343 TRACE("%s: Can't allocate bitmap of %dx%d\n", __func__
,
347 BRect
rect(0.0, 0.0, fWidth
, fHeight
);
348 fBitmap
= new (std::nothrow
) BBitmap(rect
, fColorSpace
);
349 if (fBitmap
== NULL
) {
350 TRACE("%s: Can't create bitmap!\n", __func__
);
354 TRACE("%s: New bitmap size: %" B_PRId32
" x %" B_PRId32
"\n", __func__
,
355 fBitmap
->Bounds().IntegerWidth(), fBitmap
->Bounds().IntegerHeight());
359 void *data
= fBitmap
->Bits();
360 memset(data
, 0xcc, fBitmap
->BitsLength());