1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2006-2012, Haiku, Inc. All rights reserved. 3bf215546Sopenharmony_ci * Distributed under the terms of the MIT License. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Authors: 6bf215546Sopenharmony_ci * Jérôme Duval, korli@users.berlios.de 7bf215546Sopenharmony_ci * Philippe Houdoin, philippe.houdoin@free.fr 8bf215546Sopenharmony_ci * Artur Wyszynski, harakash@gmail.com 9bf215546Sopenharmony_ci * Alexander von Gluck IV, kallisti5@unixzen.com 10bf215546Sopenharmony_ci */ 11bf215546Sopenharmony_ci 12bf215546Sopenharmony_ci 13bf215546Sopenharmony_ci#include "SoftwareRenderer.h" 14bf215546Sopenharmony_ci 15bf215546Sopenharmony_ci#include <Autolock.h> 16bf215546Sopenharmony_ci#include <interface/DirectWindowPrivate.h> 17bf215546Sopenharmony_ci#include <GraphicsDefs.h> 18bf215546Sopenharmony_ci#include <Screen.h> 19bf215546Sopenharmony_ci#include <stdio.h> 20bf215546Sopenharmony_ci#include <sys/time.h> 21bf215546Sopenharmony_ci#include <new> 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#ifdef DEBUG 25bf215546Sopenharmony_ci# define TRACE(x...) printf("SoftwareRenderer: " x) 26bf215546Sopenharmony_ci# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__) 27bf215546Sopenharmony_ci#else 28bf215546Sopenharmony_ci# define TRACE(x...) 29bf215546Sopenharmony_ci# define CALLED() 30bf215546Sopenharmony_ci#endif 31bf215546Sopenharmony_ci#define ERROR(x...) printf("SoftwareRenderer: " x) 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ciextern const char* color_space_name(color_space space); 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ciextern "C" _EXPORT BGLRenderer* 38bf215546Sopenharmony_ciinstantiate_gl_renderer(BGLView *view, ulong opts) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci return new SoftwareRenderer(view, opts); 41bf215546Sopenharmony_ci} 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistruct RasBuf32 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci int32 width, height, stride; 46bf215546Sopenharmony_ci int32 orgX, orgY; 47bf215546Sopenharmony_ci int32 *colors; 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci RasBuf32(int32 width, int32 height, int32 stride, int32 orgX, int32 orgY, int32 *colors): 50bf215546Sopenharmony_ci width(width), height(height), stride(stride), orgX(orgX), orgY(orgY), colors(colors) 51bf215546Sopenharmony_ci {} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci RasBuf32(BBitmap *bmp) 54bf215546Sopenharmony_ci { 55bf215546Sopenharmony_ci width = bmp->Bounds().IntegerWidth() + 1; 56bf215546Sopenharmony_ci height = bmp->Bounds().IntegerHeight() + 1; 57bf215546Sopenharmony_ci stride = bmp->BytesPerRow()/4; 58bf215546Sopenharmony_ci orgX = 0; 59bf215546Sopenharmony_ci orgY = 0; 60bf215546Sopenharmony_ci colors = (int32*)bmp->Bits(); 61bf215546Sopenharmony_ci } 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci RasBuf32(direct_buffer_info *info) 64bf215546Sopenharmony_ci { 65bf215546Sopenharmony_ci width = 0x7fffffff; 66bf215546Sopenharmony_ci height = 0x7fffffff; 67bf215546Sopenharmony_ci stride = info->bytes_per_row/4; 68bf215546Sopenharmony_ci orgX = 0; 69bf215546Sopenharmony_ci orgY = 0; 70bf215546Sopenharmony_ci colors = (int32*)info->bits; 71bf215546Sopenharmony_ci } 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci void ClipSize(int32 x, int32 y, int32 w, int32 h) 74bf215546Sopenharmony_ci { 75bf215546Sopenharmony_ci if (x < 0) {w += x; x = 0;} 76bf215546Sopenharmony_ci if (y < 0) {h += y; y = 0;} 77bf215546Sopenharmony_ci if (x + w > width) {w = width - x;} 78bf215546Sopenharmony_ci if (y + h > height) {h = height - y;} 79bf215546Sopenharmony_ci if ((w > 0) && (h > 0)) { 80bf215546Sopenharmony_ci colors += y*stride + x; 81bf215546Sopenharmony_ci width = w; 82bf215546Sopenharmony_ci height = h; 83bf215546Sopenharmony_ci } else { 84bf215546Sopenharmony_ci width = 0; height = 0; colors = NULL; 85bf215546Sopenharmony_ci } 86bf215546Sopenharmony_ci if (x + orgX > 0) {orgX += x;} else {orgX = 0;} 87bf215546Sopenharmony_ci if (y + orgY > 0) {orgY += y;} else {orgY = 0;} 88bf215546Sopenharmony_ci } 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci void ClipRect(int32 l, int32 t, int32 r, int32 b) 91bf215546Sopenharmony_ci { 92bf215546Sopenharmony_ci ClipSize(l, t, r - l, b - t); 93bf215546Sopenharmony_ci } 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci void Shift(int32 dx, int32 dy) 96bf215546Sopenharmony_ci { 97bf215546Sopenharmony_ci orgX += dx; 98bf215546Sopenharmony_ci orgY += dy; 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci void Clear(int32 color) 102bf215546Sopenharmony_ci { 103bf215546Sopenharmony_ci RasBuf32 dst = *this; 104bf215546Sopenharmony_ci dst.stride -= dst.width; 105bf215546Sopenharmony_ci for (; dst.height > 0; dst.height--) { 106bf215546Sopenharmony_ci for (int32 i = dst.width; i > 0; i--) 107bf215546Sopenharmony_ci *dst.colors++ = color; 108bf215546Sopenharmony_ci dst.colors += dst.stride; 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci } 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci void Blit(RasBuf32 src) 113bf215546Sopenharmony_ci { 114bf215546Sopenharmony_ci RasBuf32 dst = *this; 115bf215546Sopenharmony_ci int32 x, y; 116bf215546Sopenharmony_ci x = src.orgX - orgX; 117bf215546Sopenharmony_ci y = src.orgY - orgY; 118bf215546Sopenharmony_ci dst.ClipSize(x, y, src.width, src.height); 119bf215546Sopenharmony_ci src.ClipSize(-x, -y, width, height); 120bf215546Sopenharmony_ci for (; dst.height > 0; dst.height--) { 121bf215546Sopenharmony_ci memcpy(dst.colors, src.colors, 4*dst.width); 122bf215546Sopenharmony_ci dst.colors += dst.stride; 123bf215546Sopenharmony_ci src.colors += src.stride; 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci}; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ciSoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options) 129bf215546Sopenharmony_ci : 130bf215546Sopenharmony_ci BGLRenderer(view, options), 131bf215546Sopenharmony_ci fDirectModeEnabled(false), 132bf215546Sopenharmony_ci fInfo(NULL), 133bf215546Sopenharmony_ci fInfoLocker("info locker"), 134bf215546Sopenharmony_ci fOptions(options), 135bf215546Sopenharmony_ci fColorSpace(B_NO_COLOR_SPACE) 136bf215546Sopenharmony_ci{ 137bf215546Sopenharmony_ci CALLED(); 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci // Initialize the "Haiku Software GL Pipe" 140bf215546Sopenharmony_ci time_t beg; 141bf215546Sopenharmony_ci time_t end; 142bf215546Sopenharmony_ci beg = time(NULL); 143bf215546Sopenharmony_ci fContextObj = new GalliumContext(options); 144bf215546Sopenharmony_ci end = time(NULL); 145bf215546Sopenharmony_ci TRACE("Haiku Software GL Pipe initialization time: %f.\n", 146bf215546Sopenharmony_ci difftime(end, beg)); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci BRect b = view->Bounds(); 149bf215546Sopenharmony_ci fColorSpace = BScreen(view->Window()).ColorSpace(); 150bf215546Sopenharmony_ci TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace)); 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci fWidth = (GLint)b.IntegerWidth(); 153bf215546Sopenharmony_ci fHeight = (GLint)b.IntegerHeight(); 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci // Initialize the first "Haiku Software GL Pipe" context 156bf215546Sopenharmony_ci beg = time(NULL); 157bf215546Sopenharmony_ci fContextID = fContextObj->CreateContext(this); 158bf215546Sopenharmony_ci end = time(NULL); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci if (fContextID < 0) 161bf215546Sopenharmony_ci ERROR("%s: There was an error creating the context!\n", __func__); 162bf215546Sopenharmony_ci else { 163bf215546Sopenharmony_ci TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n", 164bf215546Sopenharmony_ci __func__, difftime(end, beg)); 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci if (!fContextObj->GetCurrentContext()) 168bf215546Sopenharmony_ci LockGL(); 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ciSoftwareRenderer::~SoftwareRenderer() 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci CALLED(); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci if (fContextObj) 177bf215546Sopenharmony_ci delete fContextObj; 178bf215546Sopenharmony_ci} 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_civoid 182bf215546Sopenharmony_ciSoftwareRenderer::LockGL() 183bf215546Sopenharmony_ci{ 184bf215546Sopenharmony_ci// CALLED(); 185bf215546Sopenharmony_ci BGLRenderer::LockGL(); 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci color_space cs = BScreen(GLView()->Window()).ColorSpace(); 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci { 190bf215546Sopenharmony_ci BAutolock lock(fInfoLocker); 191bf215546Sopenharmony_ci if (fDirectModeEnabled && fInfo != NULL) { 192bf215546Sopenharmony_ci fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left; 193bf215546Sopenharmony_ci fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci fContextObj->Validate(fWidth, fHeight); 197bf215546Sopenharmony_ci fColorSpace = cs; 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci // do not hold fInfoLocker here to avoid deadlock 201bf215546Sopenharmony_ci fContextObj->SetCurrentContext(true, fContextID); 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_civoid 206bf215546Sopenharmony_ciSoftwareRenderer::UnlockGL() 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci// CALLED(); 209bf215546Sopenharmony_ci if ((fOptions & BGL_DOUBLE) == 0) { 210bf215546Sopenharmony_ci SwapBuffers(); 211bf215546Sopenharmony_ci } 212bf215546Sopenharmony_ci fContextObj->SetCurrentContext(false, fContextID); 213bf215546Sopenharmony_ci BGLRenderer::UnlockGL(); 214bf215546Sopenharmony_ci} 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_civoid 218bf215546Sopenharmony_ciSoftwareRenderer::Display(BBitmap *bitmap, BRect *updateRect) 219bf215546Sopenharmony_ci{ 220bf215546Sopenharmony_ci// CALLED(); 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci if (!fDirectModeEnabled) { 223bf215546Sopenharmony_ci // TODO: avoid timeout 224bf215546Sopenharmony_ci if (GLView()->LockLooperWithTimeout(1000) == B_OK) { 225bf215546Sopenharmony_ci GLView()->DrawBitmap(bitmap, B_ORIGIN); 226bf215546Sopenharmony_ci GLView()->UnlockLooper(); 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci } else { 229bf215546Sopenharmony_ci BAutolock lock(fInfoLocker); 230bf215546Sopenharmony_ci if (fInfo != NULL) { 231bf215546Sopenharmony_ci RasBuf32 srcBuf(bitmap); 232bf215546Sopenharmony_ci RasBuf32 dstBuf(fInfo); 233bf215546Sopenharmony_ci for (uint32 i = 0; i < fInfo->clip_list_count; i++) { 234bf215546Sopenharmony_ci clipping_rect *clip = &fInfo->clip_list[i]; 235bf215546Sopenharmony_ci RasBuf32 dstClip = dstBuf; 236bf215546Sopenharmony_ci dstClip.ClipRect(clip->left, clip->top, clip->right + 1, clip->bottom + 1); 237bf215546Sopenharmony_ci dstClip.Shift(-fInfo->window_bounds.left, -fInfo->window_bounds.top); 238bf215546Sopenharmony_ci dstClip.Blit(srcBuf); 239bf215546Sopenharmony_ci } 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_civoid 246bf215546Sopenharmony_ciSoftwareRenderer::SwapBuffers(bool vsync) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci BScreen screen(GLView()->Window()); 249bf215546Sopenharmony_ci fContextObj->SwapBuffers(fContextID); 250bf215546Sopenharmony_ci fContextObj->Validate(fWidth, fHeight); 251bf215546Sopenharmony_ci if (vsync) 252bf215546Sopenharmony_ci screen.WaitForRetrace(); 253bf215546Sopenharmony_ci} 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_civoid 256bf215546Sopenharmony_ciSoftwareRenderer::Draw(BRect updateRect) 257bf215546Sopenharmony_ci{ 258bf215546Sopenharmony_ci// CALLED(); 259bf215546Sopenharmony_ci fContextObj->Draw(fContextID, updateRect); 260bf215546Sopenharmony_ci} 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_cistatus_t 264bf215546Sopenharmony_ciSoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap) 265bf215546Sopenharmony_ci{ 266bf215546Sopenharmony_ci CALLED(); 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci // TODO: implement 269bf215546Sopenharmony_ci return B_ERROR; 270bf215546Sopenharmony_ci} 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_cistatus_t 274bf215546Sopenharmony_ciSoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location) 275bf215546Sopenharmony_ci{ 276bf215546Sopenharmony_ci CALLED(); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci // TODO: implement 279bf215546Sopenharmony_ci return B_ERROR; 280bf215546Sopenharmony_ci} 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_civoid 284bf215546Sopenharmony_ciSoftwareRenderer::EnableDirectMode(bool enabled) 285bf215546Sopenharmony_ci{ 286bf215546Sopenharmony_ci fDirectModeEnabled = enabled; 287bf215546Sopenharmony_ci} 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_civoid 291bf215546Sopenharmony_ciSoftwareRenderer::DirectConnected(direct_buffer_info *info) 292bf215546Sopenharmony_ci{ 293bf215546Sopenharmony_ci// CALLED(); 294bf215546Sopenharmony_ci BAutolock lock(fInfoLocker); 295bf215546Sopenharmony_ci if (info) { 296bf215546Sopenharmony_ci if (!fInfo) { 297bf215546Sopenharmony_ci fInfo = (direct_buffer_info *)calloc(1, 298bf215546Sopenharmony_ci DIRECT_BUFFER_INFO_AREA_SIZE); 299bf215546Sopenharmony_ci } 300bf215546Sopenharmony_ci memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE); 301bf215546Sopenharmony_ci } else if (fInfo) { 302bf215546Sopenharmony_ci free(fInfo); 303bf215546Sopenharmony_ci fInfo = NULL; 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci} 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_civoid 309bf215546Sopenharmony_ciSoftwareRenderer::FrameResized(float width, float height) 310bf215546Sopenharmony_ci{ 311bf215546Sopenharmony_ci TRACE("%s: %f x %f\n", __func__, width, height); 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci BAutolock lock(fInfoLocker); 314bf215546Sopenharmony_ci fWidth = (GLuint)width; 315bf215546Sopenharmony_ci fHeight = (GLuint)height; 316bf215546Sopenharmony_ci} 317