softpipe: Initial work on Gallium renderer
* This is still early, but I want to track the development in tree. * swpipe will support Gallium softpipe or llvmpipe (llvm pipe will give improved software rendering permance when llvm is included at os build time) * Used Artur Wyszynski's original code as a road map... however a *lot* has changed. * Crashes at startup.. not in image yet
This commit is contained in:
@@ -4,6 +4,9 @@ SubDir HAIKU_TOP src add-ons opengl ;
|
|||||||
SubInclude HAIKU_TOP src add-ons opengl swrast ;
|
SubInclude HAIKU_TOP src add-ons opengl swrast ;
|
||||||
SubInclude HAIKU_TOP src add-ons opengl swrast_legacy ;
|
SubInclude HAIKU_TOP src add-ons opengl swrast_legacy ;
|
||||||
|
|
||||||
|
# Haiku Gallium Software Renderer
|
||||||
|
SubInclude HAIKU_TOP src add-ons opengl swpipe ;
|
||||||
|
|
||||||
# SubInclude HAIKU_TOP src add-ons opengl nvidia ;
|
# SubInclude HAIKU_TOP src add-ons opengl nvidia ;
|
||||||
# SubInclude HAIKU_TOP src add-ons opengl radeon ;
|
# SubInclude HAIKU_TOP src add-ons opengl radeon ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,546 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Artur Wyszynski, [email protected]
|
||||||
|
* Alexander von Gluck IV, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "GalliumContext.h"
|
||||||
|
|
||||||
|
#include "GLView.h"
|
||||||
|
|
||||||
|
#include "bitmap_wrapper.h"
|
||||||
|
extern "C" {
|
||||||
|
#include "glapi/glapi.h"
|
||||||
|
#include "main/context.h"
|
||||||
|
#include "main/framebuffer.h"
|
||||||
|
#include "main/renderbuffer.h"
|
||||||
|
#include "pipe/p_format.h"
|
||||||
|
#include "state_tracker/st_cb_fbo.h"
|
||||||
|
#include "state_tracker/st_cb_flush.h"
|
||||||
|
#include "state_tracker/st_context.h"
|
||||||
|
#include "state_tracker/st_gl_api.h"
|
||||||
|
#include "state_tracker/st_manager.h"
|
||||||
|
#include "state_tracker/sw_winsys.h"
|
||||||
|
#include "softpipe/sp_context.h"
|
||||||
|
#include "softpipe/sp_public.h"
|
||||||
|
#include "softpipe/sp_texture.h"
|
||||||
|
#ifdef USE_LLVMPIPE
|
||||||
|
#include "llvmpipe/lp_context.h"
|
||||||
|
#include "llvmpipe/lp_public.h"
|
||||||
|
#include "llvmpipe/lp_texture.h"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define TRACE_CONTEXT
|
||||||
|
#ifdef TRACE_CONTEXT
|
||||||
|
# define TRACE(x...) printf("GalliumContext: " x)
|
||||||
|
# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...)
|
||||||
|
# define CALLED()
|
||||||
|
#endif
|
||||||
|
#define ERROR(x...) printf("GalliumContext: " x)
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
hgl_viewport(struct gl_context* glctx, GLint x, GLint y,
|
||||||
|
GLsizei width, GLsizei height)
|
||||||
|
{
|
||||||
|
TRACE("%s(glctx: %p, x: %d, y: %d, width: %d, height: %d\n",
|
||||||
|
__FUNCTION__, glctx, x, y, width, height);
|
||||||
|
struct hgl_context *context = (struct hgl_context*)glctx->DriverCtx;
|
||||||
|
|
||||||
|
int32 w, h;
|
||||||
|
get_bitmap_size(context->bitmap, &w, &h);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// TODO: mesa_resize_framebuffer? Need to investigate where this went
|
||||||
|
if (context->draw)
|
||||||
|
st_resize_framebuffer(context->draw->stfb, w, h);
|
||||||
|
if (context->read)
|
||||||
|
st_resize_framebuffer(context->read->stfb, w, h);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hgl_fill_st_visual(st_visual* stVisual, gl_config* glVisual)
|
||||||
|
{
|
||||||
|
memset(stVisual, 0, sizeof(*stVisual));
|
||||||
|
|
||||||
|
// Determine color format
|
||||||
|
if (glVisual->redBits == 8) {
|
||||||
|
if (glVisual->alphaBits == 8)
|
||||||
|
stVisual->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
else
|
||||||
|
stVisual->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
|
||||||
|
} else {
|
||||||
|
stVisual->color_format = PIPE_FORMAT_B5G6R5_UNORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine depth stencil format
|
||||||
|
switch (glVisual->depthBits) {
|
||||||
|
default:
|
||||||
|
case 0:
|
||||||
|
stVisual->depth_stencil_format = PIPE_FORMAT_NONE;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
stVisual->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
if (glVisual->stencilBits == 0) {
|
||||||
|
stVisual->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM;
|
||||||
|
// or PIPE_FORMAT_X8Z24_UNORM?
|
||||||
|
} else {
|
||||||
|
stVisual->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
|
||||||
|
// or PIPE_FORMAT_S8_UINT_Z24_UNORM?
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
stVisual->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stVisual->accum_format = (glVisual->haveAccumBuffer)
|
||||||
|
? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
|
||||||
|
|
||||||
|
stVisual->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
|
||||||
|
stVisual->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
|
||||||
|
if (glVisual->doubleBufferMode) {
|
||||||
|
stVisual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
|
||||||
|
stVisual->render_buffer = ST_ATTACHMENT_BACK_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glVisual->stereoMode) {
|
||||||
|
stVisual->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
|
||||||
|
if (glVisual->doubleBufferMode)
|
||||||
|
stVisual->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glVisual->haveDepthBuffer || glVisual->haveStencilBuffer)
|
||||||
|
stVisual->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static INLINE unsigned
|
||||||
|
round_up(unsigned n, unsigned multiple)
|
||||||
|
{
|
||||||
|
return (n + multiple - 1) & ~(multiple - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* winsys hooks */
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hook_winsys_destroy(struct sw_winsys* winsys)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
FREE(winsys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
hook_winsys_is_displaytarget_format_supported(struct sw_winsys* winsys,
|
||||||
|
unsigned tex_usage, enum pipe_format format)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
// TODO STUB
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct sw_displaytarget*
|
||||||
|
hook_winsys_displaytarget_create(struct sw_winsys* winsys, unsigned tex_usage,
|
||||||
|
enum pipe_format format, unsigned width, unsigned height,
|
||||||
|
unsigned alignment, unsigned* stride)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
// TODO STUB
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct sw_displaytarget*
|
||||||
|
hook_winsys_displaytarget_from_handle(struct sw_winsys* winsys,
|
||||||
|
const struct pipe_resource* templat, struct winsys_handle* whandle,
|
||||||
|
unsigned* stride)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
// TODO STUB
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
hook_winsys_displaytarget_get_handle(struct sw_winsys* winsys,
|
||||||
|
struct sw_displaytarget* disptarget, struct winsys_handle* whandle)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
// TODO STUB
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void*
|
||||||
|
hook_winsys_displaytarget_map(struct sw_winsys* winsys,
|
||||||
|
struct sw_displaytarget* disptarget, unsigned flags)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
// TODO STUB
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hook_winsys_displaytarget_unmap(struct sw_winsys* winsys,
|
||||||
|
struct sw_displaytarget* disptarget)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
// TODO STUB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hook_winsys_displaytarget_display(struct sw_winsys* winsys,
|
||||||
|
struct sw_displaytarget* disptarget, void* context_private)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
// TODO STUB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hook_winsys_displaytarget_destroy(struct sw_winsys* winsys,
|
||||||
|
struct sw_displaytarget* disptarget)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
// TODO STUB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GalliumContext::GalliumContext(ulong options)
|
||||||
|
:
|
||||||
|
fOptions(options),
|
||||||
|
fCurrentContext(0),
|
||||||
|
fScreen(NULL)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
CreateScreen();
|
||||||
|
|
||||||
|
pipe_mutex_init(fMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GalliumContext::~GalliumContext()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
pipe_mutex_lock(fMutex);
|
||||||
|
uint32 i;
|
||||||
|
for (i = 0; i < CONTEXT_MAX; i++) {
|
||||||
|
// TODO: Delete each context
|
||||||
|
//if (fContext[i])
|
||||||
|
// hsp_delete_context(i + 1);
|
||||||
|
}
|
||||||
|
pipe_mutex_unlock(fMutex);
|
||||||
|
|
||||||
|
pipe_mutex_destroy(fMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GalliumContext::CreateScreen()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
struct sw_winsys* winsys = CALLOC_STRUCT(sw_winsys);
|
||||||
|
|
||||||
|
if (!winsys) {
|
||||||
|
ERROR("%s: Couldn't alloc sw_winsys!\n", __FUNCTION__);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach winsys hooks for Haiku
|
||||||
|
// gdi_create_sw_winsys is a good Mesa example
|
||||||
|
winsys->destroy = hook_winsys_destroy;
|
||||||
|
winsys->is_displaytarget_format_supported
|
||||||
|
= hook_winsys_is_displaytarget_format_supported;
|
||||||
|
winsys->displaytarget_create = hook_winsys_displaytarget_create;
|
||||||
|
winsys->displaytarget_from_handle = hook_winsys_displaytarget_from_handle;
|
||||||
|
winsys->displaytarget_get_handle = hook_winsys_displaytarget_get_handle;
|
||||||
|
winsys->displaytarget_map = hook_winsys_displaytarget_map;
|
||||||
|
winsys->displaytarget_unmap = hook_winsys_displaytarget_unmap;
|
||||||
|
winsys->displaytarget_display = hook_winsys_displaytarget_display;
|
||||||
|
winsys->displaytarget_destroy = hook_winsys_displaytarget_destroy;
|
||||||
|
|
||||||
|
#if USE_LLVMPIPE
|
||||||
|
fScreen = llvmpipe_create_screen(winsys);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (fScreen == NULL)
|
||||||
|
fScreen = softpipe_create_screen(winsys);
|
||||||
|
|
||||||
|
if (fScreen == NULL) {
|
||||||
|
ERROR("%s: Couldn't create screen!\n", __FUNCTION__);
|
||||||
|
FREE(winsys);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* driverName = fScreen->get_name(fScreen);
|
||||||
|
TRACE("%s: Using %s driver.\n", __func__, driverName);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
context_id
|
||||||
|
GalliumContext::CreateContext(Bitmap *bitmap)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
struct hgl_context* context = CALLOC_STRUCT(hgl_context);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
ERROR("%s: Couldn't create pipe context!\n", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the initial things out context needs
|
||||||
|
context->bitmap = bitmap;
|
||||||
|
context->colorSpace = get_bitmap_color_space(bitmap);
|
||||||
|
context->draw = NULL;
|
||||||
|
context->read = NULL;
|
||||||
|
context->st = NULL;
|
||||||
|
|
||||||
|
context->api = st_gl_api_create();
|
||||||
|
if (!context->api) {
|
||||||
|
ERROR("%s: Couldn't obtain Mesa state tracker API!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->manager = CALLOC_STRUCT(st_manager);
|
||||||
|
if (!context->manager) {
|
||||||
|
ERROR("%s: Couldn't allocate Mesa state tracker manager!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate visual configuration
|
||||||
|
const GLboolean rgbFlag = ((fOptions & BGL_INDEX) == 0);
|
||||||
|
const GLboolean alphaFlag = ((fOptions & BGL_ALPHA) == BGL_ALPHA);
|
||||||
|
const GLboolean dblFlag = ((fOptions & BGL_DOUBLE) == BGL_DOUBLE);
|
||||||
|
const GLboolean stereoFlag = false;
|
||||||
|
const GLint depth = (fOptions & BGL_DEPTH) ? 24 : 0;
|
||||||
|
const GLint stencil = (fOptions & BGL_STENCIL) ? 8 : 0;
|
||||||
|
const GLint accum = 0; // (options & BGL_ACCUM) ? 16 : 0;
|
||||||
|
const GLint red = rgbFlag ? 8 : 0;
|
||||||
|
const GLint green = rgbFlag ? 8 : 0;
|
||||||
|
const GLint blue = rgbFlag ? 8 : 0;
|
||||||
|
const GLint alpha = alphaFlag ? 8 : 0;
|
||||||
|
|
||||||
|
TRACE("rgb :\t%d\n", (bool)rgbFlag);
|
||||||
|
TRACE("alpha :\t%d\n", (bool)alphaFlag);
|
||||||
|
TRACE("dbl :\t%d\n", (bool)dblFlag);
|
||||||
|
TRACE("stereo :\t%d\n", (bool)stereoFlag);
|
||||||
|
TRACE("depth :\t%d\n", depth);
|
||||||
|
TRACE("stencil :\t%d\n", stencil);
|
||||||
|
TRACE("accum :\t%d\n", accum);
|
||||||
|
TRACE("red :\t%d\n", red);
|
||||||
|
TRACE("green :\t%d\n", green);
|
||||||
|
TRACE("blue :\t%d\n", blue);
|
||||||
|
TRACE("alpha :\t%d\n", alpha);
|
||||||
|
|
||||||
|
gl_config* glVisual = _mesa_create_visual(dblFlag, stereoFlag, red, green,
|
||||||
|
blue, alpha, depth, stencil, accum, accum, accum, alpha ? accum : 0, 1);
|
||||||
|
|
||||||
|
if (!glVisual) {
|
||||||
|
ERROR("%s: Couldn't create Mesa visual!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("depthBits :\t%d\n", glVisual->depthBits);
|
||||||
|
TRACE("stencilBits :\t%d\n", glVisual->stencilBits);
|
||||||
|
|
||||||
|
// Convert Mesa calculated visual into state tracker visual
|
||||||
|
struct st_visual stVisual;
|
||||||
|
hgl_fill_st_visual(&stVisual, glVisual);
|
||||||
|
|
||||||
|
// We need to assign the screen *before* calling st_api create_context
|
||||||
|
context->manager->screen = fScreen;
|
||||||
|
|
||||||
|
// Build state tracker attributes
|
||||||
|
struct st_context_attribs attribs;
|
||||||
|
memset(&attribs, 0, sizeof(attribs));
|
||||||
|
attribs.options.force_glsl_extensions_warn = false;
|
||||||
|
attribs.profile = ST_PROFILE_DEFAULT;
|
||||||
|
attribs.visual = stVisual;
|
||||||
|
attribs.major = 1;
|
||||||
|
attribs.minor = 0;
|
||||||
|
//attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
|
||||||
|
|
||||||
|
struct st_api* api = context->api;
|
||||||
|
|
||||||
|
// Create context using state tracker api call
|
||||||
|
enum st_context_error result;
|
||||||
|
context->st = api->create_context(api, context->manager, &attribs,
|
||||||
|
&result, context->st);
|
||||||
|
|
||||||
|
if (!context->st) {
|
||||||
|
ERROR("%s: Couldn't create mesa state tracker context!\n",
|
||||||
|
__func__);
|
||||||
|
switch (result) {
|
||||||
|
case ST_CONTEXT_SUCCESS:
|
||||||
|
ERROR("%s: State tracker error: SUCCESS?\n", __func__);
|
||||||
|
break;
|
||||||
|
case ST_CONTEXT_ERROR_NO_MEMORY:
|
||||||
|
ERROR("%s: State tracker error: NO_MEMORY\n", __func__);
|
||||||
|
break;
|
||||||
|
case ST_CONTEXT_ERROR_BAD_API:
|
||||||
|
ERROR("%s: State tracker error: BAD_API\n", __func__);
|
||||||
|
break;
|
||||||
|
case ST_CONTEXT_ERROR_BAD_VERSION:
|
||||||
|
ERROR("%s: State tracker error: BAD_VERSION\n", __func__);
|
||||||
|
break;
|
||||||
|
case ST_CONTEXT_ERROR_BAD_FLAG:
|
||||||
|
ERROR("%s: State tracker error: BAD_FLAG\n", __func__);
|
||||||
|
break;
|
||||||
|
case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE:
|
||||||
|
ERROR("%s: State tracker error: BAD_ATTRIBUTE\n", __func__);
|
||||||
|
break;
|
||||||
|
case ST_CONTEXT_ERROR_UNKNOWN_FLAG:
|
||||||
|
ERROR("%s: State tracker error: UNKNOWN_FLAG\n", __func__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FREE(context);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!context->st->st_manager_private);
|
||||||
|
context->st->st_manager_private = (void*)context;
|
||||||
|
|
||||||
|
// TODO!
|
||||||
|
//context->st->ctx->DriverCtx = context;
|
||||||
|
//context->st->ctx->Driver.Viewport = hgl_viewport;
|
||||||
|
|
||||||
|
// TODO: Closely review this next context logic...
|
||||||
|
context_id contextNext = -1;
|
||||||
|
|
||||||
|
pipe_mutex_lock(fMutex);
|
||||||
|
context_id i;
|
||||||
|
for (i = 0; i < CONTEXT_MAX; i++) {
|
||||||
|
if (fContext[i] == NULL) {
|
||||||
|
fContext[i] = context;
|
||||||
|
contextNext = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pipe_mutex_unlock(fMutex);
|
||||||
|
|
||||||
|
if (contextNext < 0) {
|
||||||
|
ERROR("%s: The next context is invalid... something went wrong!\n",
|
||||||
|
__func__);
|
||||||
|
//st_destroy_context(context->st);
|
||||||
|
FREE(context);
|
||||||
|
_mesa_destroy_visual(glVisual);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("%s: context #%" B_PRIu64 " is the next available context\n",
|
||||||
|
__func__, contextNext);
|
||||||
|
|
||||||
|
return contextNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
if (contextID < 0 || contextID > CONTEXT_MAX) {
|
||||||
|
ERROR("%s: Invalid context ID range!\n", __func__);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe_mutex_lock(fMutex);
|
||||||
|
context_id oldContextID = fCurrentContext;
|
||||||
|
struct hgl_context* context = fContext[contextID];
|
||||||
|
pipe_mutex_unlock(fMutex);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
ERROR("%s: Invalid context provided (#%" B_PRIu64 ")!\n",
|
||||||
|
__func__, contextID);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st_api* api = context->api;
|
||||||
|
|
||||||
|
if (!bitmap) {
|
||||||
|
ERROR("%s: Invalid bitmap provided!\n", __func__);
|
||||||
|
api->make_current(context->api, NULL, NULL, NULL);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything seems valid, lets set the new context.
|
||||||
|
fCurrentContext = contextID;
|
||||||
|
|
||||||
|
if (oldContextID > 0 && oldContextID != contextID) {
|
||||||
|
fContext[oldContextID]->st->flush(fContext[oldContextID]->st,
|
||||||
|
0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: WinSysDrawBuffer & WinSysReadBuffer?
|
||||||
|
api->make_current(context->api, context->st, context->read, context->draw);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Anything else? st_api_make_current
|
||||||
|
|
||||||
|
context->bitmap = bitmap;
|
||||||
|
//context->st->pipe->priv = context;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GalliumContext::SwapBuffers(context_id contextID)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
pipe_mutex_lock(fMutex);
|
||||||
|
struct hgl_context *context = fContext[contextID];
|
||||||
|
pipe_mutex_unlock(fMutex);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
ERROR("%s: context not found\n", __func__);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//pipe_mutex_lock(context->draw->mutex);
|
||||||
|
|
||||||
|
// TODO: Where did st_notify_swapbuffers go?
|
||||||
|
//st_notify_swapbuffers(context->draw->stfb);
|
||||||
|
|
||||||
|
// TODO: Where did st_get_framebuffer_surface go?
|
||||||
|
//struct pipe_surface *surface;
|
||||||
|
//st_get_framebuffer_surface(context->draw->stfb, ST_SURFACE_BACK_LEFT,
|
||||||
|
// &surface);
|
||||||
|
|
||||||
|
context->st->flush(context->st, ST_FLUSH_FRONT, NULL);
|
||||||
|
|
||||||
|
// TODO: Flush the frontbuffer!
|
||||||
|
//hsp_dev->hsp_winsys->flush_frontbuffer(hsp_dev->screen, surface,
|
||||||
|
// context->bitmap);
|
||||||
|
|
||||||
|
//pipe_mutex_unlock(context->draw->mutex);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Alexander von Gluck IV, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef CALLIUMCONTEXT_H
|
||||||
|
#define CALLIUMCONTEXT_H
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "state_tracker/st_api.h"
|
||||||
|
#include "pipe/p_compiler.h"
|
||||||
|
#include "pipe/p_screen.h"
|
||||||
|
#include "os/os_thread.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "bitmap_wrapper.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define CONTEXT_MAX 32
|
||||||
|
|
||||||
|
// HACK: offsetof must be redefined before loading sp_context.h
|
||||||
|
// in GalliumContext.cpp
|
||||||
|
#undef offsetof
|
||||||
|
#define offsetof( type, member ) ((size_t) &((type *)0)->member)
|
||||||
|
|
||||||
|
|
||||||
|
typedef int64 context_id;
|
||||||
|
|
||||||
|
struct hgl_context
|
||||||
|
{
|
||||||
|
struct st_api* api;
|
||||||
|
// State Tracker API
|
||||||
|
struct st_manager* manager;
|
||||||
|
// State Tracker Manager
|
||||||
|
struct st_context_iface* st;
|
||||||
|
// State Tracker Interface Object
|
||||||
|
|
||||||
|
Bitmap* bitmap;
|
||||||
|
color_space colorSpace;
|
||||||
|
|
||||||
|
struct st_framebuffer_iface* draw;
|
||||||
|
struct st_framebuffer_iface* read;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GalliumContext {
|
||||||
|
public:
|
||||||
|
GalliumContext(ulong options);
|
||||||
|
~GalliumContext();
|
||||||
|
|
||||||
|
context_id CreateContext(Bitmap* bitmap);
|
||||||
|
context_id GetCurrentContext() { return fCurrentContext; };
|
||||||
|
status_t SetCurrentContext(Bitmap *bitmap,
|
||||||
|
context_id contextID);
|
||||||
|
|
||||||
|
status_t SwapBuffers(context_id contextID);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t CreateScreen();
|
||||||
|
void Flush();
|
||||||
|
|
||||||
|
ulong fOptions;
|
||||||
|
|
||||||
|
struct hgl_context* fContext[CONTEXT_MAX];
|
||||||
|
context_id fCurrentContext;
|
||||||
|
|
||||||
|
struct pipe_screen* fScreen;
|
||||||
|
pipe_mutex fMutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CALLIUMCONTEXT_H */
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons opengl swpipe ;
|
||||||
|
|
||||||
|
UseHeaders [ FDirName $(HAIKU_MESA_DIR) src gallium auxiliary ] ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_MESA_DIR) src gallium drivers ] ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_MESA_DIR) src gallium include ] ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_MESA_DIR) src mapi ] ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_MESA_DIR) src mesa ] ;
|
||||||
|
|
||||||
|
local sources =
|
||||||
|
SoftwareRenderer.cpp
|
||||||
|
GalliumContext.cpp
|
||||||
|
bitmap_wrapper.cpp ;
|
||||||
|
|
||||||
|
UsePrivateHeaders interface ;
|
||||||
|
SubDirSysHdrs $(HAIKU_MESA_HEADERS) ;
|
||||||
|
Includes [ FGristFiles $(sources) ] : $(HAIKU_MESA_HEADERS_DEPENDENCY) ;
|
||||||
|
|
||||||
|
#AddResources Software\ Renderer : SoftwareRenderer.rdef ;
|
||||||
|
|
||||||
|
Addon Software\ Renderer :
|
||||||
|
$(sources)
|
||||||
|
: libGL.so
|
||||||
|
$(HAIKU_MESA_DIR)/lib.haiku/libgallium.a
|
||||||
|
$(HAIKU_MESA_DIR)/lib.haiku/libsoftpipe.a
|
||||||
|
be translation $(TARGET_LIBSUPC++)
|
||||||
|
;
|
||||||
@@ -0,0 +1,359 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006-2009, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jérôme Duval, [email protected]
|
||||||
|
* Philippe Houdoin, [email protected]
|
||||||
|
* Artur Wyszynski, [email protected]
|
||||||
|
* Alexander von Gluck IV, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "SoftwareRenderer.h"
|
||||||
|
|
||||||
|
#include <Autolock.h>
|
||||||
|
#include <DirectWindowPrivate.h>
|
||||||
|
#include <GraphicsDefs.h>
|
||||||
|
#include <Screen.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
|
||||||
|
#define TRACE_SOFTWARE
|
||||||
|
#ifdef TRACE_SOFTWARE
|
||||||
|
# define TRACE(x...) printf("SoftwareRenderer: " x)
|
||||||
|
# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...)
|
||||||
|
# define CALLED()
|
||||||
|
#endif
|
||||||
|
#define ERROR(x...) printf("SoftwareRenderer: " x)
|
||||||
|
|
||||||
|
|
||||||
|
extern const char* color_space_name(color_space space);
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" _EXPORT BGLRenderer*
|
||||||
|
instantiate_gl_renderer(BGLView *view, ulong opts, BGLDispatcher *dispatcher)
|
||||||
|
{
|
||||||
|
return new SoftwareRenderer(view, opts, dispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options,
|
||||||
|
BGLDispatcher* dispatcher)
|
||||||
|
:
|
||||||
|
BGLRenderer(view, options, dispatcher),
|
||||||
|
fBitmap(NULL),
|
||||||
|
fDirectModeEnabled(false),
|
||||||
|
fInfo(NULL),
|
||||||
|
fInfoLocker("info locker"),
|
||||||
|
fOptions(options),
|
||||||
|
fColorSpace(B_NO_COLOR_SPACE)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
// Disable double buffer for the moment.
|
||||||
|
options &= ~BGL_DOUBLE;
|
||||||
|
|
||||||
|
// Initialize the "Haiku Software GL Pipe"
|
||||||
|
time_t beg;
|
||||||
|
time_t end;
|
||||||
|
beg = time(NULL);
|
||||||
|
fContextObj = new GalliumContext(options);
|
||||||
|
end = time(NULL);
|
||||||
|
TRACE("Haiku Software GL Pipe initialization time: %f.\n",
|
||||||
|
difftime(end, beg));
|
||||||
|
|
||||||
|
// Allocate a bitmap
|
||||||
|
BRect b = view->Bounds();
|
||||||
|
fColorSpace = BScreen(view->Window()).ColorSpace();
|
||||||
|
TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace));
|
||||||
|
|
||||||
|
fWidth = (GLint)b.IntegerWidth();
|
||||||
|
fHeight = (GLint)b.IntegerHeight();
|
||||||
|
fNewWidth = fWidth;
|
||||||
|
fNewHeight = fHeight;
|
||||||
|
|
||||||
|
_AllocateBitmap();
|
||||||
|
|
||||||
|
// Initialize the first "Haiku Software GL Pipe" context
|
||||||
|
beg = time(NULL);
|
||||||
|
fContextID = fContextObj->CreateContext(fBitmap);
|
||||||
|
end = time(NULL);
|
||||||
|
|
||||||
|
if (fContextID < 0)
|
||||||
|
ERROR("%s: There was an error creating the context!\n", __func__);
|
||||||
|
else {
|
||||||
|
TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",
|
||||||
|
__func__, difftime(end, beg));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fContextObj->GetCurrentContext())
|
||||||
|
LockGL();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SoftwareRenderer::~SoftwareRenderer()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
if (fContextObj)
|
||||||
|
delete fContextObj;
|
||||||
|
if (fBitmap)
|
||||||
|
delete fBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SoftwareRenderer::LockGL()
|
||||||
|
{
|
||||||
|
// CALLED();
|
||||||
|
BGLRenderer::LockGL();
|
||||||
|
|
||||||
|
color_space cs = BScreen(GLView()->Window()).ColorSpace();
|
||||||
|
|
||||||
|
BAutolock lock(fInfoLocker);
|
||||||
|
if (fDirectModeEnabled && fInfo != NULL) {
|
||||||
|
fNewWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;// + 1;
|
||||||
|
fNewHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;// + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fBitmap && cs == fColorSpace && fNewWidth == fWidth
|
||||||
|
&& fNewHeight == fHeight) {
|
||||||
|
fContextObj->SetCurrentContext(fBitmap, fContextID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fColorSpace = cs;
|
||||||
|
fWidth = fNewWidth;
|
||||||
|
fHeight = fNewHeight;
|
||||||
|
|
||||||
|
_AllocateBitmap();
|
||||||
|
fContextObj->SetCurrentContext(fBitmap, fContextID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SoftwareRenderer::UnlockGL()
|
||||||
|
{
|
||||||
|
// CALLED();
|
||||||
|
if ((fOptions & BGL_DOUBLE) == 0) {
|
||||||
|
SwapBuffers();
|
||||||
|
}
|
||||||
|
fContextObj->SetCurrentContext(NULL, fContextID);
|
||||||
|
BGLRenderer::UnlockGL();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SoftwareRenderer::SwapBuffers(bool vsync)
|
||||||
|
{
|
||||||
|
// CALLED();
|
||||||
|
if (!fBitmap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BScreen screen(GLView()->Window());
|
||||||
|
|
||||||
|
fContextObj->SwapBuffers(fContextID);
|
||||||
|
|
||||||
|
BAutolock lock(fInfoLocker);
|
||||||
|
|
||||||
|
if (!fDirectModeEnabled || fInfo == NULL) {
|
||||||
|
if (GLView()->LockLooperWithTimeout(1000) == B_OK) {
|
||||||
|
GLView()->DrawBitmap(fBitmap, B_ORIGIN);
|
||||||
|
GLView()->UnlockLooper();
|
||||||
|
if (vsync)
|
||||||
|
screen.WaitForRetrace();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the bitmap size still matches the size
|
||||||
|
if (fInfo->window_bounds.bottom - fInfo->window_bounds.top
|
||||||
|
!= fBitmap->Bounds().IntegerHeight() + 1
|
||||||
|
|| fInfo->window_bounds.right - fInfo->window_bounds.left
|
||||||
|
!= fBitmap->Bounds().IntegerWidth() + 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8 bytesPerPixel = fInfo->bits_per_pixel / 8;
|
||||||
|
uint32 bytesPerRow = fBitmap->BytesPerRow();
|
||||||
|
for (uint32 i = 0; i < fInfo->clip_list_count; i++) {
|
||||||
|
clipping_rect *clip = &fInfo->clip_list[i];
|
||||||
|
int32 height = clip->bottom - clip->top + 1;
|
||||||
|
int32 bytesWidth
|
||||||
|
= (clip->right - clip->left + 1) * bytesPerPixel;
|
||||||
|
bytesWidth -= bytesPerPixel;
|
||||||
|
uint8 *p = (uint8 *)fInfo->bits + clip->top
|
||||||
|
* fInfo->bytes_per_row + clip->left * bytesPerPixel;
|
||||||
|
uint8 *b = (uint8 *)fBitmap->Bits()
|
||||||
|
+ (clip->top - fInfo->window_bounds.top) * bytesPerRow
|
||||||
|
+ (clip->left - fInfo->window_bounds.left) * bytesPerPixel;
|
||||||
|
|
||||||
|
for (int y = 0; y < height - 1; y++) {
|
||||||
|
memcpy(p, b, bytesWidth);
|
||||||
|
p += fInfo->bytes_per_row;
|
||||||
|
b += bytesPerRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vsync)
|
||||||
|
screen.WaitForRetrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SoftwareRenderer::Draw(BRect updateRect)
|
||||||
|
{
|
||||||
|
// CALLED();
|
||||||
|
if ((!fDirectModeEnabled || fInfo == NULL) && fBitmap)
|
||||||
|
GLView()->DrawBitmap(fBitmap, updateRect, updateRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
color_space scs = fBitmap->ColorSpace();
|
||||||
|
color_space dcs = bitmap->ColorSpace();
|
||||||
|
|
||||||
|
if (scs != dcs && (scs != B_RGBA32 || dcs != B_RGB32)) {
|
||||||
|
ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n",
|
||||||
|
__PRETTY_FUNCTION__, color_space_name(scs), color_space_name(dcs));
|
||||||
|
return B_BAD_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BRect sr = fBitmap->Bounds();
|
||||||
|
BRect dr = bitmap->Bounds();
|
||||||
|
|
||||||
|
// int32 w1 = sr.IntegerWidth();
|
||||||
|
// int32 h1 = sr.IntegerHeight();
|
||||||
|
// int32 w2 = dr.IntegerWidth();
|
||||||
|
// int32 h2 = dr.IntegerHeight();
|
||||||
|
|
||||||
|
sr = sr & dr.OffsetBySelf(location);
|
||||||
|
dr = sr.OffsetByCopy(-location.x, -location.y);
|
||||||
|
|
||||||
|
uint8 *ps = (uint8 *) fBitmap->Bits();
|
||||||
|
uint8 *pd = (uint8 *) bitmap->Bits();
|
||||||
|
uint32 *s, *d;
|
||||||
|
uint32 y;
|
||||||
|
for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) {
|
||||||
|
s = (uint32 *)(ps + y * fBitmap->BytesPerRow());
|
||||||
|
s += (uint32) sr.left;
|
||||||
|
|
||||||
|
d = (uint32 *)(pd + (y + (uint32)(dr.top - sr.top))
|
||||||
|
* bitmap->BytesPerRow());
|
||||||
|
d += (uint32) dr.left;
|
||||||
|
memcpy(d, s, dr.IntegerWidth() * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
color_space sourceCS = bitmap->ColorSpace();
|
||||||
|
color_space destinationCS = fBitmap->ColorSpace();
|
||||||
|
|
||||||
|
if (sourceCS != destinationCS
|
||||||
|
&& (sourceCS != B_RGB32 || destinationCS != B_RGBA32)) {
|
||||||
|
ERROR("%s::CopyPixelsIn(): incompatible color space: %s != %s\n",
|
||||||
|
__PRETTY_FUNCTION__, color_space_name(sourceCS),
|
||||||
|
color_space_name(destinationCS));
|
||||||
|
return B_BAD_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BRect sr = bitmap->Bounds();
|
||||||
|
BRect dr = fBitmap->Bounds();
|
||||||
|
|
||||||
|
sr = sr & dr.OffsetBySelf(location);
|
||||||
|
dr = sr.OffsetByCopy(-location.x, -location.y);
|
||||||
|
|
||||||
|
uint8 *ps = (uint8 *) bitmap->Bits();
|
||||||
|
uint8 *pd = (uint8 *) fBitmap->Bits();
|
||||||
|
uint32 *s, *d;
|
||||||
|
uint32 y;
|
||||||
|
|
||||||
|
for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) {
|
||||||
|
s = (uint32 *)(ps + y * bitmap->BytesPerRow());
|
||||||
|
s += (uint32) sr.left;
|
||||||
|
|
||||||
|
d = (uint32 *)(pd + (y + (uint32)(dr.top - sr.top))
|
||||||
|
* fBitmap->BytesPerRow());
|
||||||
|
d += (uint32) dr.left;
|
||||||
|
|
||||||
|
memcpy(d, s, dr.IntegerWidth() * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SoftwareRenderer::EnableDirectMode(bool enabled)
|
||||||
|
{
|
||||||
|
fDirectModeEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SoftwareRenderer::DirectConnected(direct_buffer_info *info)
|
||||||
|
{
|
||||||
|
// CALLED();
|
||||||
|
BAutolock lock(fInfoLocker);
|
||||||
|
if (info) {
|
||||||
|
if (!fInfo) {
|
||||||
|
fInfo = (direct_buffer_info *)calloc(1,
|
||||||
|
DIRECT_BUFFER_INFO_AREA_SIZE);
|
||||||
|
}
|
||||||
|
memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
|
||||||
|
} else if (fInfo) {
|
||||||
|
free(fInfo);
|
||||||
|
fInfo = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SoftwareRenderer::FrameResized(float width, float height)
|
||||||
|
{
|
||||||
|
// CALLED();
|
||||||
|
BAutolock lock(fInfoLocker);
|
||||||
|
fNewWidth = (GLuint)width;
|
||||||
|
fNewHeight = (GLuint)height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SoftwareRenderer::_AllocateBitmap()
|
||||||
|
{
|
||||||
|
// CALLED();
|
||||||
|
|
||||||
|
// allocate new size of back buffer bitmap
|
||||||
|
BAutolock lock(fInfoLocker);
|
||||||
|
delete fBitmap;
|
||||||
|
fBitmap = NULL;
|
||||||
|
if (fWidth <= 1 || fHeight <= 1) {
|
||||||
|
TRACE("%s: Can't allocate bitmap of %dx%d\n", __func__,
|
||||||
|
fWidth, fHeight);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BRect rect(0.0, 0.0, fWidth - 1, fHeight - 1);
|
||||||
|
fBitmap = new (std::nothrow) BBitmap(rect, fColorSpace);
|
||||||
|
if (fBitmap == NULL) {
|
||||||
|
TRACE("%s: Can't create bitmap!\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
// debug..
|
||||||
|
void *data = fBitmap->Bits();
|
||||||
|
memset(data, 0xcc, fBitmap->BitsLength());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006-2012, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jérôme Duval, [email protected]
|
||||||
|
* Philippe Houdoin, [email protected]
|
||||||
|
* Artur Wyszynski, [email protected]
|
||||||
|
* Alexander von Gluck IV, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef SOFTWARERENDERER_H
|
||||||
|
#define SOFTWARERENDERER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "GLRenderer.h"
|
||||||
|
#include "GalliumContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
class SoftwareRenderer : public BGLRenderer {
|
||||||
|
public:
|
||||||
|
SoftwareRenderer(BGLView *view,
|
||||||
|
ulong bgl_options,
|
||||||
|
BGLDispatcher *dispatcher);
|
||||||
|
virtual ~SoftwareRenderer();
|
||||||
|
|
||||||
|
virtual void LockGL();
|
||||||
|
virtual void UnlockGL();
|
||||||
|
|
||||||
|
virtual void SwapBuffers(bool vsync = false);
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
virtual status_t CopyPixelsOut(BPoint source, BBitmap *dest);
|
||||||
|
virtual status_t CopyPixelsIn(BBitmap *source, BPoint dest);
|
||||||
|
virtual void FrameResized(float width, float height);
|
||||||
|
|
||||||
|
virtual void EnableDirectMode(bool enabled);
|
||||||
|
virtual void DirectConnected(direct_buffer_info *info);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void _AllocateBitmap();
|
||||||
|
|
||||||
|
GalliumContext* fContextObj;
|
||||||
|
BBitmap* fBitmap;
|
||||||
|
context_id fContextID;
|
||||||
|
|
||||||
|
bool fDirectModeEnabled;
|
||||||
|
direct_buffer_info* fInfo;
|
||||||
|
BLocker fInfoLocker;
|
||||||
|
ulong fOptions;
|
||||||
|
GLuint fWidth;
|
||||||
|
GLuint fHeight;
|
||||||
|
GLuint fNewWidth;
|
||||||
|
GLuint fNewHeight;
|
||||||
|
color_space fColorSpace;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SOFTPIPERENDERER_H
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Based on gallium gdi winsys
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Artur Wyszynski <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <interface/Bitmap.h>
|
||||||
|
#include <storage/File.h>
|
||||||
|
#include <support/String.h>
|
||||||
|
#include <translation/BitmapStream.h>
|
||||||
|
#include <translation/TranslatorRoster.h>
|
||||||
|
#include "bitmap_wrapper.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
static int frameNo = 0;
|
||||||
|
|
||||||
|
|
||||||
|
Bitmap*
|
||||||
|
create_bitmap(int32 width, int32 height, color_space colorSpace)
|
||||||
|
{
|
||||||
|
BBitmap *bb = new BBitmap(BRect(0, 0, width, height), colorSpace);
|
||||||
|
if (bb)
|
||||||
|
return (Bitmap*)bb;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
get_bitmap_size(const Bitmap* bitmap, int32* width, int32* height)
|
||||||
|
{
|
||||||
|
BBitmap *bb = (BBitmap*)bitmap;
|
||||||
|
if (bb && width && height) {
|
||||||
|
uint32 w = bb->Bounds().IntegerWidth() + 1;
|
||||||
|
uint32 h = bb->Bounds().IntegerHeight() + 1;
|
||||||
|
*width = w;
|
||||||
|
*height = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
color_space
|
||||||
|
get_bitmap_color_space(const Bitmap* bitmap)
|
||||||
|
{
|
||||||
|
BBitmap *bb = (BBitmap*)bitmap;
|
||||||
|
if (bb)
|
||||||
|
return bb->ColorSpace();
|
||||||
|
return B_NO_COLOR_SPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
copy_bitmap_bits(const Bitmap* bitmap, void* data, int32 length)
|
||||||
|
{
|
||||||
|
BBitmap *bb = (BBitmap*)bitmap;
|
||||||
|
if (bb) {
|
||||||
|
color_space cs = bb->ColorSpace();
|
||||||
|
bb->ImportBits(data, length, bb->BytesPerRow(), 0, cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
delete_bitmap(Bitmap* bitmap)
|
||||||
|
{
|
||||||
|
BBitmap *bb = (BBitmap*)bitmap;
|
||||||
|
delete bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
get_bitmap_bytes_per_row(const Bitmap* bitmap)
|
||||||
|
{
|
||||||
|
BBitmap *bb = (BBitmap*)bitmap;
|
||||||
|
if (bb)
|
||||||
|
return bb->BytesPerRow();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
get_bitmap_bits_length(const Bitmap* bitmap)
|
||||||
|
{
|
||||||
|
BBitmap *bb = (BBitmap*)bitmap;
|
||||||
|
if (bb)
|
||||||
|
return bb->BitsLength();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
dump_bitmap(const Bitmap* bitmap)
|
||||||
|
{
|
||||||
|
|
||||||
|
BBitmap *bb = (BBitmap*)bitmap;
|
||||||
|
if (!bb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BString filename("/boot/home/frame_");
|
||||||
|
filename << (int32)frameNo << ".png";
|
||||||
|
|
||||||
|
BTranslatorRoster *roster = BTranslatorRoster::Default();
|
||||||
|
BBitmapStream stream(bb);
|
||||||
|
BFile dump(filename, B_CREATE_FILE | B_WRITE_ONLY);
|
||||||
|
|
||||||
|
roster->Translate(&stream, NULL, NULL, &dump, 0);
|
||||||
|
|
||||||
|
frameNo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Based on gallium gdi winsys
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Artur Wyszynski <[email protected]>
|
||||||
|
*/
|
||||||
|
#ifndef __BBITMAP_WRAPPER_H__
|
||||||
|
#define __BBITMAP_WRAPPER_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <interface/GraphicsDefs.h>
|
||||||
|
#include <support/SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef void Bitmap;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
Bitmap* create_bitmap(int32 width, int32 height, color_space colorSpace);
|
||||||
|
void copy_bitmap_bits(const Bitmap* bitmap, void* data, int32 length);
|
||||||
|
|
||||||
|
void get_bitmap_size(const Bitmap* bitmap, int32* width, int32* height);
|
||||||
|
color_space get_bitmap_color_space(const Bitmap* bitmap);
|
||||||
|
int32 get_bitmap_bytes_per_row(const Bitmap* bitmap);
|
||||||
|
int32 get_bitmap_bits_length(const Bitmap* bitmap);
|
||||||
|
|
||||||
|
void delete_bitmap(Bitmap* bitmap);
|
||||||
|
void dump_bitmap(const Bitmap* bitmap);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __BBITMAP_WRAPPER_H__ */
|
||||||
Reference in New Issue
Block a user