summaryrefslogtreecommitdiffstats
path: root/client/gui
diff options
context:
space:
mode:
authorYaniv Kamay <ykamay@redhat.com>2009-12-28 00:31:35 +0200
committerYaniv Kamay <ykamay@redhat.com>2009-12-28 12:37:01 +0200
commitce480b07335d8f7d380ac302a1a6422c4fa3742b (patch)
treec60f73f0887ee0e66a11cc6d3fd723427eb19c99 /client/gui
parent2dbaf8c00c28770e48cbfc6ab3300000118d22ec (diff)
downloadspice-ce480b07335d8f7d380ac302a1a6422c4fa3742b.tar.gz
spice-ce480b07335d8f7d380ac302a1a6422c4fa3742b.tar.xz
spice-ce480b07335d8f7d380ac302a1a6422c4fa3742b.zip
client: add soft renderer and cegui
Diffstat (limited to 'client/gui')
-rw-r--r--client/gui/softrenderer.cpp372
-rw-r--r--client/gui/softrenderer.h131
-rw-r--r--client/gui/softtexture.cpp124
-rw-r--r--client/gui/softtexture.h40
4 files changed, 667 insertions, 0 deletions
diff --git a/client/gui/softrenderer.cpp b/client/gui/softrenderer.cpp
new file mode 100644
index 00000000..9e08f7a5
--- /dev/null
+++ b/client/gui/softrenderer.cpp
@@ -0,0 +1,372 @@
+#include "common.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "utils.h"
+#include "debug.h"
+
+#include "softrenderer.h"
+#include "softtexture.h"
+
+#include "CEGUIExceptions.h"
+#include "CEGUIImageCodec.h"
+#include "CEGUIDynamicModule.h"
+#include "CEGUIEventArgs.h"
+
+#define S_(X) #X
+#define STRINGIZE(X) S_(X)
+
+namespace CEGUI {
+
+SoftRenderer::SoftRenderer(uint8_t* surface, uint width, uint height, uint stride,
+ ImageCodec* codec)
+ : _surface (surface)
+ , _width (width)
+ , _height (height)
+ , _image_codec (codec)
+ , _image_codec_module (NULL)
+ , _queueing(true)
+{
+ assert(stride == _width * 4); //for now
+ if (!_image_codec) {
+ setupImageCodec();
+ }
+}
+
+SoftRenderer::~SoftRenderer()
+{
+ destroyAllTextures();
+ cleanupImageCodec();
+}
+
+
+void SoftRenderer::reset_surface(uint8_t* surface, uint width, uint height, uint stride)
+{
+ assert(stride == width * 4); //for now
+ _surface = surface;
+ _width = width;
+ _height = height;
+
+ EventArgs args;
+ fireEvent(EventDisplaySizeChanged, args, EventNamespace);
+}
+
+#if defined(CEGUI_STATIC)
+extern "C" CEGUI::ImageCodec* createImageCodec(void);
+extern "C" void destroyImageCodec(CEGUI::ImageCodec*);
+#endif
+
+void SoftRenderer::setupImageCodec()
+{
+#if defined(CEGUI_STATIC)
+ _destroy_image_codec = destroyImageCodec;
+ _image_codec = createImageCodec();
+#else
+ String _default_codec_name(STRINGIZE(TGAImageCodec/*CEGUI_DEFAULT_IMAGE_CODEC*/));
+ DynamicModule* module = NULL;
+ try {
+ DynamicModule* module = new DynamicModule(String("CEGUI") + _default_codec_name);
+
+ _destroy_image_codec = (void(*)(ImageCodec*))module->getSymbolAddress("destroyImageCodec");
+ if (!_destroy_image_codec) {
+ throw GenericException("Missing destroyImageCodec symbol");
+ }
+
+ ImageCodec* (*create_f)(void);
+ create_f = (ImageCodec* (*)(void))module->getSymbolAddress("createImageCodec");
+ if (!create_f) {
+ throw GenericException("Missing createImageCodec symbol");
+ }
+ _image_codec = create_f();
+ } catch (...) {
+ delete module;
+ throw;
+ }
+ _image_codec_module = module;
+#endif
+}
+
+
+void SoftRenderer::cleanupImageCodec()
+{
+ _destroy_image_codec(_image_codec);
+ delete _image_codec_module;
+}
+
+
+static inline uint8_t calac_pixel(uint64_t c1, uint64_t c2, uint64_t c3, uint64_t a_mul)
+{
+ //(c' * c" * a' * a" + c"' * 255 ^ 3 - c"' * a' * a" * 255) / 255^4
+
+ return uint8_t((c1 * c2 * a_mul + c3 * 255 * 255 * 255 - c3 * a_mul * 255) / (255 * 255 * 255));
+}
+
+inline void SoftRenderer::componnentAtPoint(int x_pos, int y_pos,
+ int top_left, int top_right,
+ int bottom_left, int bottom_right,
+ uint64_t& comp)
+{
+ int a = top_left + (((x_pos * (top_right - top_left)) + (1 << 15)) >> 16);
+ int b = bottom_left + (((x_pos * (bottom_right - bottom_left)) + (1 << 15)) >> 16);
+ comp = a + (((b - a) * y_pos + (1 << 15)) >> 16);
+}
+
+void SoftRenderer::colourAtPoint(int x, int x_max, int y, int y_max,
+ const ColourIRect& colours,
+ uint64_t& r, uint64_t& g,
+ uint64_t& b, uint64_t& a)
+{
+ int x_pos = (x << 16) / x_max;
+ int y_pos = (y << 16) / y_max;
+
+
+ componnentAtPoint(x_pos, y_pos, colours.top_left.r, colours.top_right.r,
+ colours.bottom_left.r, colours.bottom_right.r, r);
+ componnentAtPoint(x_pos, y_pos, colours.top_left.g, colours.top_right.g,
+ colours.bottom_left.g, colours.bottom_right.g, g);
+ componnentAtPoint(x_pos, y_pos, colours.top_left.b, colours.top_right.b,
+ colours.bottom_left.b, colours.bottom_right.b, b);
+ componnentAtPoint(x_pos, y_pos, colours.top_left.a, colours.top_right.a,
+ colours.bottom_left.a, colours.bottom_right.a, a);
+}
+
+void SoftRenderer::renderQuadWithColourRect(const QuadInfo& quad)
+{
+ uint32_t* src = quad.tex->_surf + quad.tex_src.top * (int)quad.tex->getWidth();
+ src += quad.tex_src.left;
+
+
+ int src_width = quad.tex_src.right - quad.tex_src.left;
+ int src_height = quad.tex_src.bottom - quad.tex_src.top;
+
+ int dest_width = quad.dest.right - quad.dest.left;
+ int dest_height = quad.dest.bottom - quad.dest.top;
+
+
+ uint32_t x_scale = (src_width << 16) / dest_width;
+ uint32_t y_scale = (src_height << 16) / dest_height;
+
+ uint32_t* line = (uint32_t*)_surface + quad.dest.top * _width;
+ line += quad.dest.left;
+
+ for (int i = 0; i < dest_height; line += _width, i++) {
+ uint32_t* pix = line;
+ uint32_t* src_line = src + (((i * y_scale) + (1 << 15)) >> 16) * (int)quad.tex->getWidth();
+
+ for (int j = 0; j < dest_width; pix++, j++) {
+ uint64_t r;
+ uint64_t g;
+ uint64_t b;
+ uint64_t a;
+
+ colourAtPoint(j, dest_width, i, dest_height, quad.colors, r, g, b, a);
+
+ uint8_t* tex_pix = (uint8_t*)&src_line[(((j * x_scale)+ (1 << 15)) >> 16)];
+ uint64_t a_mul = a * tex_pix[3];
+
+ ((uint8_t *)pix)[0] = calac_pixel(tex_pix[0], b, ((uint8_t *)pix)[0], a_mul);
+ ((uint8_t *)pix)[1] = calac_pixel(tex_pix[1], g, ((uint8_t *)pix)[1], a_mul);
+ ((uint8_t *)pix)[2] = calac_pixel(tex_pix[2], r, ((uint8_t *)pix)[2], a_mul);
+ }
+ }
+}
+
+void SoftRenderer::renderQuad(const QuadInfo& quad)
+{
+ if (!quad.colors.top_left.isSameColour(quad.colors.top_right) ||
+ !quad.colors.top_left.isSameColour(quad.colors.bottom_left) ||
+ !quad.colors.top_left.isSameColour(quad.colors.bottom_right)) {
+ renderQuadWithColourRect(quad);
+ return;
+ }
+
+
+ uint32_t* src = quad.tex->_surf + quad.tex_src.top * (int)quad.tex->getWidth();
+ src += quad.tex_src.left;
+
+
+ int src_width = quad.tex_src.right - quad.tex_src.left;
+ int src_height = quad.tex_src.bottom - quad.tex_src.top;
+
+ int dest_width = quad.dest.right - quad.dest.left;
+ int dest_height = quad.dest.bottom - quad.dest.top;
+
+
+ uint32_t x_scale = (src_width << 16) / dest_width;
+ uint32_t y_scale = (src_height << 16) / dest_height;
+
+ uint32_t* line = (uint32_t*)_surface + quad.dest.top * _width;
+ line += quad.dest.left;
+
+ uint64_t r = quad.colors.top_left.r;
+ uint64_t g = quad.colors.top_left.g;
+ uint64_t b = quad.colors.top_left.b;
+ uint64_t a = quad.colors.top_left.a;
+
+ for (int i = 0; i < dest_height; line += _width, i++) {
+ uint32_t* pix = line;
+ uint32_t* src_line = src + (((i * y_scale) + (1 << 15)) >> 16) * (int)quad.tex->getWidth();
+
+ for (int j = 0; j < dest_width; pix++, j++) {
+ uint8_t* tex_pix = (uint8_t*)&src_line[(((j * x_scale)+ (1 << 15)) >> 16)];
+ uint64_t a_mul = a * tex_pix[3];
+
+ ((uint8_t *)pix)[0] = calac_pixel(tex_pix[0], b, ((uint8_t *)pix)[0], a_mul);
+ ((uint8_t *)pix)[1] = calac_pixel(tex_pix[1], g, ((uint8_t *)pix)[1], a_mul);
+ ((uint8_t *)pix)[2] = calac_pixel(tex_pix[2], r, ((uint8_t *)pix)[2], a_mul);
+ }
+ }
+}
+
+inline void SoftRenderer::setRGB(ColourI& dest, const colour& src)
+{
+ dest.r = uint8_t(src.getRed()* 255);
+ dest.g = uint8_t(src.getGreen() * 255);
+ dest.b = uint8_t(src.getBlue() * 255);
+ dest.a = uint8_t(src.getAlpha() * 255);
+}
+
+void SoftRenderer::addQuad(const Rect& dest_rect, float z, const Texture* texture,
+ const Rect& texture_rect, const ColourRect& colours,
+ QuadSplitMode quad_split_mode)
+{
+ if (dest_rect.d_right <= dest_rect.d_left || dest_rect.d_bottom <= dest_rect.d_top) {
+ return;
+ }
+
+ if (texture_rect.d_right <= texture_rect.d_left ||
+ texture_rect.d_bottom <= texture_rect.d_top) {
+ return;
+ }
+
+ QuadInfo quad;
+ quad.dest.top = (int)dest_rect.d_top;
+ quad.dest.left = (int)dest_rect.d_left;
+ quad.dest.bottom = (int)dest_rect.d_bottom;
+ quad.dest.right = (int)dest_rect.d_right;
+
+ quad.tex = (const SoftTexture*)texture;
+
+ quad.tex_src.top = int(texture_rect.d_top * texture->getHeight());
+ quad.tex_src.bottom = int(texture_rect.d_bottom * texture->getHeight());
+ quad.tex_src.left = int(texture_rect.d_left * texture->getWidth());
+ quad.tex_src.right = int(texture_rect.d_right * texture->getWidth());
+
+ setRGB(quad.colors.top_left, colours.d_top_left);
+ setRGB(quad.colors.top_right, colours.d_top_right);
+ setRGB(quad.colors.bottom_left, colours.d_bottom_left);
+ setRGB(quad.colors.bottom_right, colours.d_bottom_right);
+
+ quad.z = z;
+
+ if (!_queueing) {
+ renderQuad(quad);
+ return;
+ }
+
+ _queue.insert(quad);
+}
+
+void SoftRenderer::doRender()
+{
+ QuadQueue::iterator iter = _queue.begin();
+
+ for (; iter != _queue.end(); ++iter) {
+ renderQuad(*iter);
+ }
+}
+
+void SoftRenderer::clearRenderList()
+{
+ _queue.clear();
+}
+
+void SoftRenderer::setQueueingEnabled(bool val)
+{
+ _queueing = val;
+}
+
+bool SoftRenderer::isQueueingEnabled() const
+{
+ return _queueing;
+}
+
+Texture* SoftRenderer::createTexture()
+{
+ SoftTexture* texture = new SoftTexture(this);
+ _textures.push_back(texture);
+ return texture;
+}
+
+Texture* SoftRenderer::createTexture(const String& filename,
+ const String& resourceGroup)
+{
+ SoftTexture* texture = new SoftTexture(this, filename, resourceGroup);
+ _textures.push_back(texture);
+ return texture;
+}
+
+Texture* SoftRenderer::createTexture(float size)
+{
+ SoftTexture* texture = new SoftTexture(this, (uint)size);
+ _textures.push_back(texture);
+ return texture;
+}
+
+void SoftRenderer::destroyTexture(Texture* texture)
+{
+ if (!texture) {
+ return;
+ }
+ SoftTexture* soft_texture = (SoftTexture*)texture;
+ _textures.remove(soft_texture);
+ delete soft_texture;
+}
+
+void SoftRenderer::destroyAllTextures()
+{
+ while (!_textures.empty()) {
+ SoftTexture* texture = *_textures.begin();
+ _textures.pop_front();
+ delete texture;
+ }
+}
+
+uint SoftRenderer::getMaxTextureSize() const
+{
+ return 1 << 16;
+}
+
+float SoftRenderer::getWidth() const
+{
+ return (float)_width;
+}
+
+float SoftRenderer::getHeight() const
+{
+ return (float)_height;
+}
+
+Size SoftRenderer::getSize() const
+{
+ return Size((float)_width, (float)_height);
+}
+
+Rect SoftRenderer::getRect() const
+{
+ return Rect(0, 0, (float)_width, (float)_height);
+}
+
+uint SoftRenderer::getHorzScreenDPI() const
+{
+ return 96;
+}
+
+uint SoftRenderer::getVertScreenDPI() const
+{
+ return 96;
+}
+
+}
+
+
diff --git a/client/gui/softrenderer.h b/client/gui/softrenderer.h
new file mode 100644
index 00000000..939eb38b
--- /dev/null
+++ b/client/gui/softrenderer.h
@@ -0,0 +1,131 @@
+#ifndef _directfbrenderer_h_
+#define _directfbrenderer_h_
+
+#include <stdint.h>
+#include <list>
+#include <set>
+
+#include "CEGUIRenderer.h"
+#include "CEGUIColourRect.h"
+#include "CEGUIRect.h"
+
+
+namespace CEGUI
+{
+ class SoftTexture;
+ class ImageCodec;
+
+ class SoftRenderer : public Renderer
+ {
+ public:
+ SoftRenderer(uint8_t* surface, uint width, uint height, uint stride,
+ ImageCodec* codec = NULL);
+ virtual ~SoftRenderer();
+
+ void reset_surface(uint8_t* surface, uint width, uint height, uint stride);
+
+ virtual void addQuad(const Rect& dest_rect, float z, const Texture* tex,
+ const Rect& texture_rect, const ColourRect& colours,
+ QuadSplitMode quad_split_mode);
+ virtual void doRender();
+ virtual void clearRenderList();
+ virtual void setQueueingEnabled(bool setting);
+ virtual bool isQueueingEnabled() const;
+
+ virtual Texture* createTexture();
+ virtual Texture* createTexture(const String& filename,
+ const String& resourceGroup);
+ virtual Texture* createTexture(float size);
+ virtual void destroyTexture(Texture* texture);
+ virtual void destroyAllTextures();
+ virtual uint getMaxTextureSize() const;
+
+ virtual float getWidth() const;
+ virtual float getHeight() const;
+ virtual Size getSize() const;
+ virtual Rect getRect() const;
+
+ virtual uint getHorzScreenDPI() const;
+ virtual uint getVertScreenDPI() const;
+
+ ImageCodec* getImageCodec() { return _image_codec;}
+
+ private:
+ void setupImageCodec();
+ void cleanupImageCodec();
+ struct QuadInfo;
+ void renderQuad(const QuadInfo& quad);
+ void renderQuadWithColourRect(const QuadInfo& quad);
+
+ class ColourI {
+ public:
+
+ bool isSameColour(const ColourI& other) const
+ {
+ return other.r == r && other.g == g && other.b == b && other.a == a;
+ }
+
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
+ };
+
+ static inline void setRGB(ColourI& dest, const colour& src);
+ static inline void componnentAtPoint(int x_pos, int y_pos,
+ int top_left, int top_right,
+ int bottom_left, int bottom_right,
+ uint64_t& comp);
+
+ struct ColourIRect {
+ ColourI top_left;
+ ColourI top_right;
+ ColourI bottom_left;
+ ColourI bottom_right;
+ };
+
+ static void colourAtPoint(int x, int x_max, int y, int y_max,
+ const ColourIRect& colours,
+ uint64_t& r, uint64_t& g,
+ uint64_t& b, uint64_t& a);
+
+ private:
+ uint8_t* _surface;
+ int _width;
+ int _height;
+ ImageCodec* _image_codec;
+ DynamicModule* _image_codec_module;
+ void (*_destroy_image_codec)(ImageCodec*);
+ bool _queueing;
+
+ struct RectI {
+ int left;
+ int top;
+ int right;
+ int bottom;
+ };
+
+ struct QuadInfo {
+ RectI dest;
+ const SoftTexture* tex;
+ RectI tex_src;
+ ColourIRect colors;
+ float z;
+
+ bool operator < (const QuadInfo& other) const
+ {
+ return z > other.z;
+ }
+ };
+
+ typedef std::multiset<QuadInfo> QuadQueue;
+ QuadQueue _queue;
+
+ typedef std::list<SoftTexture *> TexturesList;
+ TexturesList _textures;
+ };
+}
+
+#endif
+
+
diff --git a/client/gui/softtexture.cpp b/client/gui/softtexture.cpp
new file mode 100644
index 00000000..562edeab
--- /dev/null
+++ b/client/gui/softtexture.cpp
@@ -0,0 +1,124 @@
+#include "common.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "softtexture.h"
+#include "softrenderer.h"
+
+#include "CEGUIImageCodec.h"
+#include "CEGUISystem.h"
+#include "CEGUIExceptions.h"
+
+namespace CEGUI
+{
+
+
+SoftTexture::SoftTexture(Renderer* owner)
+ : Texture (owner)
+ , _surf (NULL)
+ , _width (0)
+ , _height (0)
+{
+
+}
+
+SoftTexture::SoftTexture(Renderer* owner, uint size)
+ : Texture (owner)
+ , _surf (new uint32[size * size])
+ , _width (size)
+ , _height (size)
+{
+
+}
+
+SoftTexture::SoftTexture(Renderer* owner, const String& filename,
+ const String& resourceGroup)
+ : Texture (owner)
+ , _surf (NULL)
+ , _width (0)
+ , _height (0)
+{
+ loadFromFile(filename, resourceGroup);
+}
+
+
+SoftTexture::~SoftTexture()
+{
+ freeSurf();
+}
+
+void SoftTexture::freeSurf()
+{
+ _width = _height = 0;
+ delete[] _surf;
+ _surf = NULL;
+}
+
+void SoftTexture::loadFromFile(const String& filename, const String& resourceGroup)
+{
+ freeSurf();
+ SoftRenderer* renderer = static_cast<SoftRenderer*>(getRenderer());
+ RawDataContainer texture_file;
+ ResourceProvider* resource_provider = System::getSingleton().getResourceProvider();
+ resource_provider->loadRawDataContainer(filename, texture_file, resourceGroup);
+ ImageCodec *codec = renderer->getImageCodec();
+ Texture* res = codec->load(texture_file, this);
+ resource_provider->unloadRawDataContainer(texture_file);
+ if (!res) {
+ throw RendererException("load from file failed");
+ }
+}
+
+void SoftTexture::loadFromMemory(const void* buffPtr, uint buffWidth,
+ uint buffHeight,
+ PixelFormat pixelFormat)
+{
+ freeSurf();
+ _surf = new uint32[buffWidth * buffHeight];
+ _width = buffWidth;
+ _height = buffHeight;
+
+ switch (pixelFormat) {
+ case PF_RGBA: {
+ const uint32_t *src = static_cast<const uint32_t *>(buffPtr);
+ uint32* line = _surf;
+ uint32* end_line = _surf + _width * _height;
+ for (int i = 0; line != end_line; line += _width, i++) {
+ uint32* pixel = line;
+ uint32* end_pixel = pixel + _width;
+ for (; pixel != end_pixel; pixel++, src++) {
+ ((uint8_t*)pixel)[0] = ((uint8_t*)src)[2];
+ ((uint8_t*)pixel)[1] = ((uint8_t*)src)[1];
+ ((uint8_t*)pixel)[2] = ((uint8_t*)src)[0];
+ ((uint8_t*)pixel)[3] = ((uint8_t*)src)[3];
+ }
+ }
+ break;
+ }
+ case PF_RGB: {
+ const uint8_t *src = static_cast<const uint8_t *>(buffPtr);
+ uint32* line = _surf;
+ uint32* end_line = _surf + _width * _height;
+ for (int i = 0; line != end_line; line += _width, i++) {
+ uint8* pixel = (uint8*)line;
+ uint8* end_pixel = (uint8*)(line + _width);
+ for (; pixel != end_pixel; pixel += 4, src += 3) {
+ pixel[2] = src[0];
+ pixel[1] = src[1];
+ pixel[0] = src[2];
+ pixel[3] = 0xff;
+ }
+ }
+ break;
+ }
+ default:
+ throw RendererException("invalid pixel format");
+ }
+}
+
+
+}
+
diff --git a/client/gui/softtexture.h b/client/gui/softtexture.h
new file mode 100644
index 00000000..37617f29
--- /dev/null
+++ b/client/gui/softtexture.h
@@ -0,0 +1,40 @@
+
+#ifndef _softtexture_h_
+#define _softtexture_h_
+
+#include <stdint.h>
+#include "CEGUIBase.h"
+#include "CEGUITexture.h"
+
+namespace CEGUI
+{
+ class SoftTexture : public Texture
+ {
+ public:
+ SoftTexture(Renderer* owner);
+ SoftTexture(Renderer* owner, uint size);
+ SoftTexture(Renderer* owner, const String& filename,
+ const String& resourceGroup);
+ virtual ~SoftTexture();
+
+ virtual ushort getWidth(void) const { return _width;}
+ virtual ushort getHeight(void) const { return _height;}
+
+ virtual void loadFromFile(const String& filename, const String& resourceGroup);
+ virtual void loadFromMemory(const void* buffPtr, uint buffWidth, uint buffHeight,
+ PixelFormat pixelFormat);
+
+ private:
+ void freeSurf();
+
+ private:
+ uint32_t* _surf;
+ ushort _width;
+ ushort _height;
+
+ friend class SoftRenderer;
+ };
+}
+
+#endif
+