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>
24 #define TRACE_SOFTWARE
26 # define TRACE(x...) printf("SoftwareRenderer: " x)
27 # define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
32 #define ERROR(x...) printf("SoftwareRenderer: " x)
35 extern const char* color_space_name(color_space space
);
38 extern "C" _EXPORT BGLRenderer
*
39 instantiate_gl_renderer(BGLView
*view
, ulong opts
, BGLDispatcher
*dispatcher
)
41 return new SoftwareRenderer(view
, opts
, dispatcher
);
44 SoftwareRenderer::SoftwareRenderer(BGLView
*view
, ulong options
,
45 BGLDispatcher
* dispatcher
)
47 BGLRenderer(view
, options
, dispatcher
),
49 fDirectModeEnabled(false),
51 fInfoLocker("info locker"),
53 fColorSpace(B_NO_COLOR_SPACE
)
57 // Disable double buffer for the moment.
58 options
&= ~BGL_DOUBLE
;
60 // Initialize the "Haiku Software GL Pipe"
64 fContextObj
= new GalliumContext(options
);
66 TRACE("Haiku Software GL Pipe initialization time: %f.\n",
70 BRect b
= view
->Bounds();
71 fColorSpace
= BScreen(view
->Window()).ColorSpace();
72 TRACE("%s: Colorspace:\t%s\n", __func__
, color_space_name(fColorSpace
));
74 fWidth
= (GLint
)b
.IntegerWidth();
75 fHeight
= (GLint
)b
.IntegerHeight();
81 // Initialize the first "Haiku Software GL Pipe" context
83 fContextID
= fContextObj
->CreateContext(fBitmap
);
87 ERROR("%s: There was an error creating the context!\n", __func__
);
89 TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",
90 __func__
, difftime(end
, beg
));
93 if (!fContextObj
->GetCurrentContext())
98 SoftwareRenderer::~SoftwareRenderer()
110 SoftwareRenderer::LockGL()
113 BGLRenderer::LockGL();
115 color_space cs
= BScreen(GLView()->Window()).ColorSpace();
117 BAutolock
lock(fInfoLocker
);
118 if (fDirectModeEnabled
&& fInfo
!= NULL
) {
119 fNewWidth
= fInfo
->window_bounds
.right
- fInfo
->window_bounds
.left
;
121 fNewHeight
= fInfo
->window_bounds
.bottom
- fInfo
->window_bounds
.top
;
125 if (fBitmap
&& cs
== fColorSpace
&& fNewWidth
== fWidth
126 && fNewHeight
== fHeight
) {
127 fContextObj
->SetCurrentContext(fBitmap
, fContextID
);
133 fHeight
= fNewHeight
;
136 fContextObj
->SetCurrentContext(fBitmap
, fContextID
);
141 SoftwareRenderer::UnlockGL()
144 if ((fOptions
& BGL_DOUBLE
) == 0) {
147 fContextObj
->SetCurrentContext(NULL
, fContextID
);
148 BGLRenderer::UnlockGL();
153 SoftwareRenderer::SwapBuffers(bool vsync
)
159 BScreen
screen(GLView()->Window());
161 fContextObj
->SwapBuffers(fContextID
);
163 BAutolock
lock(fInfoLocker
);
165 if (!fDirectModeEnabled
|| fInfo
== NULL
) {
166 if (GLView()->LockLooperWithTimeout(1000) == B_OK
) {
167 GLView()->DrawBitmap(fBitmap
, B_ORIGIN
);
168 GLView()->UnlockLooper();
170 screen
.WaitForRetrace();
175 // check the bitmap size still matches the size
176 if (fInfo
->window_bounds
.bottom
- fInfo
->window_bounds
.top
177 != fBitmap
->Bounds().IntegerHeight()
178 || fInfo
->window_bounds
.right
- fInfo
->window_bounds
.left
179 != fBitmap
->Bounds().IntegerWidth()) {
180 ERROR("%s: Bitmap size doesn't match size!\n", __func__
);
183 uint8 bytesPerPixel
= fInfo
->bits_per_pixel
/ 8;
184 uint32 bytesPerRow
= fBitmap
->BytesPerRow();
185 for (uint32 i
= 0; i
< fInfo
->clip_list_count
; i
++) {
186 clipping_rect
*clip
= &fInfo
->clip_list
[i
];
187 int32 height
= clip
->bottom
- clip
->top
+ 1;
189 = (clip
->right
- clip
->left
+ 1) * bytesPerPixel
;
190 bytesWidth
-= bytesPerPixel
;
191 uint8
*p
= (uint8
*)fInfo
->bits
+ clip
->top
192 * fInfo
->bytes_per_row
+ clip
->left
* bytesPerPixel
;
193 uint8
*b
= (uint8
*)fBitmap
->Bits()
194 + (clip
->top
- fInfo
->window_bounds
.top
) * bytesPerRow
195 + (clip
->left
- fInfo
->window_bounds
.left
) * bytesPerPixel
;
197 for (int y
= 0; y
< height
- 1; y
++) {
198 memcpy(p
, b
, bytesWidth
);
199 p
+= fInfo
->bytes_per_row
;
205 screen
.WaitForRetrace();
210 SoftwareRenderer::Draw(BRect updateRect
)
213 if ((!fDirectModeEnabled
|| fInfo
== NULL
) && fBitmap
)
214 GLView()->DrawBitmap(fBitmap
, updateRect
, updateRect
);
219 SoftwareRenderer::CopyPixelsOut(BPoint location
, BBitmap
*bitmap
)
222 color_space scs
= fBitmap
->ColorSpace();
223 color_space dcs
= bitmap
->ColorSpace();
225 if (scs
!= dcs
&& (scs
!= B_RGBA32
|| dcs
!= B_RGB32
)) {
226 ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n",
227 __PRETTY_FUNCTION__
, color_space_name(scs
), color_space_name(dcs
));
231 BRect sr
= fBitmap
->Bounds();
232 BRect dr
= bitmap
->Bounds();
234 // int32 w1 = sr.IntegerWidth();
235 // int32 h1 = sr.IntegerHeight();
236 // int32 w2 = dr.IntegerWidth();
237 // int32 h2 = dr.IntegerHeight();
239 sr
= sr
& dr
.OffsetBySelf(location
);
240 dr
= sr
.OffsetByCopy(-location
.x
, -location
.y
);
242 uint8
*ps
= (uint8
*) fBitmap
->Bits();
243 uint8
*pd
= (uint8
*) bitmap
->Bits();
246 for (y
= (uint32
) sr
.top
; y
<= (uint32
) sr
.bottom
; y
++) {
247 s
= (uint32
*)(ps
+ y
* fBitmap
->BytesPerRow());
248 s
+= (uint32
) sr
.left
;
250 d
= (uint32
*)(pd
+ (y
+ (uint32
)(dr
.top
- sr
.top
))
251 * bitmap
->BytesPerRow());
252 d
+= (uint32
) dr
.left
;
253 memcpy(d
, s
, dr
.IntegerWidth() * 4);
261 SoftwareRenderer::CopyPixelsIn(BBitmap
*bitmap
, BPoint location
)
265 color_space sourceCS
= bitmap
->ColorSpace();
266 color_space destinationCS
= fBitmap
->ColorSpace();
268 if (sourceCS
!= destinationCS
269 && (sourceCS
!= B_RGB32
|| destinationCS
!= B_RGBA32
)) {
270 ERROR("%s::CopyPixelsIn(): incompatible color space: %s != %s\n",
271 __PRETTY_FUNCTION__
, color_space_name(sourceCS
),
272 color_space_name(destinationCS
));
276 BRect sr
= bitmap
->Bounds();
277 BRect dr
= fBitmap
->Bounds();
279 sr
= sr
& dr
.OffsetBySelf(location
);
280 dr
= sr
.OffsetByCopy(-location
.x
, -location
.y
);
282 uint8
*ps
= (uint8
*) bitmap
->Bits();
283 uint8
*pd
= (uint8
*) fBitmap
->Bits();
287 for (y
= (uint32
) sr
.top
; y
<= (uint32
) sr
.bottom
; y
++) {
288 s
= (uint32
*)(ps
+ y
* bitmap
->BytesPerRow());
289 s
+= (uint32
) sr
.left
;
291 d
= (uint32
*)(pd
+ (y
+ (uint32
)(dr
.top
- sr
.top
))
292 * fBitmap
->BytesPerRow());
293 d
+= (uint32
) dr
.left
;
295 memcpy(d
, s
, dr
.IntegerWidth() * 4);
303 SoftwareRenderer::EnableDirectMode(bool enabled
)
305 fDirectModeEnabled
= enabled
;
310 SoftwareRenderer::DirectConnected(direct_buffer_info
*info
)
313 BAutolock
lock(fInfoLocker
);
316 fInfo
= (direct_buffer_info
*)calloc(1,
317 DIRECT_BUFFER_INFO_AREA_SIZE
);
319 memcpy(fInfo
, info
, DIRECT_BUFFER_INFO_AREA_SIZE
);
328 SoftwareRenderer::FrameResized(float width
, float 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__
);
360 void *data
= fBitmap
->Bits();
361 memset(data
, 0xcc, fBitmap
->BitsLength());