Path: blob/21.2-virgl/src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp
4565 views
/*1* Copyright 2006-2012, Haiku, Inc. All rights reserved.2* Distributed under the terms of the MIT License.3*4* Authors:5* Jérôme Duval, [email protected]6* Philippe Houdoin, [email protected]7* Artur Wyszynski, [email protected]8* Alexander von Gluck IV, [email protected]9*/101112#include "SoftwareRenderer.h"1314#include <Autolock.h>15#include <interface/DirectWindowPrivate.h>16#include <GraphicsDefs.h>17#include <Screen.h>18#include <stdio.h>19#include <sys/time.h>20#include <new>212223#ifdef DEBUG24# define TRACE(x...) printf("SoftwareRenderer: " x)25# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)26#else27# define TRACE(x...)28# define CALLED()29#endif30#define ERROR(x...) printf("SoftwareRenderer: " x)313233extern const char* color_space_name(color_space space);343536extern "C" _EXPORT BGLRenderer*37instantiate_gl_renderer(BGLView *view, ulong opts)38{39return new SoftwareRenderer(view, opts);40}4142struct RasBuf3243{44int32 width, height, stride;45int32 orgX, orgY;46int32 *colors;4748RasBuf32(int32 width, int32 height, int32 stride, int32 orgX, int32 orgY, int32 *colors):49width(width), height(height), stride(stride), orgX(orgX), orgY(orgY), colors(colors)50{}5152RasBuf32(BBitmap *bmp)53{54width = bmp->Bounds().IntegerWidth() + 1;55height = bmp->Bounds().IntegerHeight() + 1;56stride = bmp->BytesPerRow()/4;57orgX = 0;58orgY = 0;59colors = (int32*)bmp->Bits();60}6162RasBuf32(direct_buffer_info *info)63{64width = 0x7fffffff;65height = 0x7fffffff;66stride = info->bytes_per_row/4;67orgX = 0;68orgY = 0;69colors = (int32*)info->bits;70}7172void ClipSize(int32 x, int32 y, int32 w, int32 h)73{74if (x < 0) {w += x; x = 0;}75if (y < 0) {h += y; y = 0;}76if (x + w > width) {w = width - x;}77if (y + h > height) {h = height - y;}78if ((w > 0) && (h > 0)) {79colors += y*stride + x;80width = w;81height = h;82} else {83width = 0; height = 0; colors = NULL;84}85if (x + orgX > 0) {orgX += x;} else {orgX = 0;}86if (y + orgY > 0) {orgY += y;} else {orgY = 0;}87}8889void ClipRect(int32 l, int32 t, int32 r, int32 b)90{91ClipSize(l, t, r - l, b - t);92}9394void Shift(int32 dx, int32 dy)95{96orgX += dx;97orgY += dy;98}99100void Clear(int32 color)101{102RasBuf32 dst = *this;103dst.stride -= dst.width;104for (; dst.height > 0; dst.height--) {105for (int32 i = dst.width; i > 0; i--)106*dst.colors++ = color;107dst.colors += dst.stride;108}109}110111void Blit(RasBuf32 src)112{113RasBuf32 dst = *this;114int32 x, y;115x = src.orgX - orgX;116y = src.orgY - orgY;117dst.ClipSize(x, y, src.width, src.height);118src.ClipSize(-x, -y, width, height);119for (; dst.height > 0; dst.height--) {120memcpy(dst.colors, src.colors, 4*dst.width);121dst.colors += dst.stride;122src.colors += src.stride;123}124}125};126127SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options)128:129BGLRenderer(view, options),130fDirectModeEnabled(false),131fInfo(NULL),132fInfoLocker("info locker"),133fOptions(options),134fColorSpace(B_NO_COLOR_SPACE)135{136CALLED();137138// Initialize the "Haiku Software GL Pipe"139time_t beg;140time_t end;141beg = time(NULL);142fContextObj = new GalliumContext(options);143end = time(NULL);144TRACE("Haiku Software GL Pipe initialization time: %f.\n",145difftime(end, beg));146147BRect b = view->Bounds();148fColorSpace = BScreen(view->Window()).ColorSpace();149TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace));150151fWidth = (GLint)b.IntegerWidth();152fHeight = (GLint)b.IntegerHeight();153154// Initialize the first "Haiku Software GL Pipe" context155beg = time(NULL);156fContextID = fContextObj->CreateContext(this);157end = time(NULL);158159if (fContextID < 0)160ERROR("%s: There was an error creating the context!\n", __func__);161else {162TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",163__func__, difftime(end, beg));164}165166if (!fContextObj->GetCurrentContext())167LockGL();168}169170171SoftwareRenderer::~SoftwareRenderer()172{173CALLED();174175if (fContextObj)176delete fContextObj;177}178179180void181SoftwareRenderer::LockGL()182{183// CALLED();184BGLRenderer::LockGL();185186color_space cs = BScreen(GLView()->Window()).ColorSpace();187188{189BAutolock lock(fInfoLocker);190if (fDirectModeEnabled && fInfo != NULL) {191fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;192fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;193}194195fContextObj->Validate(fWidth, fHeight);196fColorSpace = cs;197}198199// do not hold fInfoLocker here to avoid deadlock200fContextObj->SetCurrentContext(true, fContextID);201}202203204void205SoftwareRenderer::UnlockGL()206{207// CALLED();208if ((fOptions & BGL_DOUBLE) == 0) {209SwapBuffers();210}211fContextObj->SetCurrentContext(false, fContextID);212BGLRenderer::UnlockGL();213}214215216void217SoftwareRenderer::Display(BBitmap *bitmap, BRect *updateRect)218{219// CALLED();220221if (!fDirectModeEnabled) {222// TODO: avoid timeout223if (GLView()->LockLooperWithTimeout(1000) == B_OK) {224GLView()->DrawBitmap(bitmap, B_ORIGIN);225GLView()->UnlockLooper();226}227} else {228BAutolock lock(fInfoLocker);229if (fInfo != NULL) {230RasBuf32 srcBuf(bitmap);231RasBuf32 dstBuf(fInfo);232for (uint32 i = 0; i < fInfo->clip_list_count; i++) {233clipping_rect *clip = &fInfo->clip_list[i];234RasBuf32 dstClip = dstBuf;235dstClip.ClipRect(clip->left, clip->top, clip->right + 1, clip->bottom + 1);236dstClip.Shift(-fInfo->window_bounds.left, -fInfo->window_bounds.top);237dstClip.Blit(srcBuf);238}239}240}241}242243244void245SoftwareRenderer::SwapBuffers(bool vsync)246{247BScreen screen(GLView()->Window());248fContextObj->SwapBuffers(fContextID);249fContextObj->Validate(fWidth, fHeight);250if (vsync)251screen.WaitForRetrace();252}253254void255SoftwareRenderer::Draw(BRect updateRect)256{257// CALLED();258fContextObj->Draw(fContextID, updateRect);259}260261262status_t263SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap)264{265CALLED();266267// TODO: implement268return B_ERROR;269}270271272status_t273SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location)274{275CALLED();276277// TODO: implement278return B_ERROR;279}280281282void283SoftwareRenderer::EnableDirectMode(bool enabled)284{285fDirectModeEnabled = enabled;286}287288289void290SoftwareRenderer::DirectConnected(direct_buffer_info *info)291{292// CALLED();293BAutolock lock(fInfoLocker);294if (info) {295if (!fInfo) {296fInfo = (direct_buffer_info *)calloc(1,297DIRECT_BUFFER_INFO_AREA_SIZE);298}299memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);300} else if (fInfo) {301free(fInfo);302fInfo = NULL;303}304}305306307void308SoftwareRenderer::FrameResized(float width, float height)309{310TRACE("%s: %f x %f\n", __func__, width, height);311312BAutolock lock(fInfoLocker);313fWidth = (GLuint)width;314fHeight = (GLuint)height;315}316317318