#include "glutil.hpp"
#include "sdl_lightmap.hpp"
#include "sdl_texture.hpp"
+#include "sdl_surface_data.hpp"
#include "drawing_context.hpp"
#include "drawing_request.hpp"
#include "renderer.hpp"
{
screen = SDL_GetVideoSurface();
- width = screen->w;
- height = screen->h;
+ float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
+ float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
+ if(xfactor < yfactor)
+ {
+ numerator = config->screenwidth;
+ denominator = SCREEN_WIDTH;
+ }
+ else
+ {
+ numerator = config->screenheight;
+ denominator = SCREEN_HEIGHT;
+ }
+
+ LIGHTMAP_DIV = 8 * numerator / denominator;
+
+ width = screen->w / LIGHTMAP_DIV;
+ height = screen->h / LIGHTMAP_DIV;
red_channel = (Uint8 *)malloc(width * height * sizeof(Uint8));
green_channel = (Uint8 *)malloc(width * height * sizeof(Uint8));
{
}
+//#define BILINEAR
+
+#ifdef BILINEAR
+ namespace
+ {
+ void merge(Uint8 color[3], Uint8 color0[3], Uint8 color1[3], int rem, int total)
+ {
+ color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total;
+ color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total;
+ color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total;
+ }
+ }
+#endif
+
void
Lightmap::do_draw()
{
// FIXME: This is really slow
- int bpp = screen->format->BytesPerPixel;
- Uint8 *pixel = (Uint8 *) screen->pixels;
- int loc = 0;
- for(int y = 0;y < height;y++) {
- for(int x = 0;x < width;x++, pixel += bpp, loc++) {
+ if(LIGHTMAP_DIV == 1)
+ {
+ int bpp = screen->format->BytesPerPixel;
+ if(SDL_MUSTLOCK(screen))
+ {
+ SDL_LockSurface(screen);
+ }
+ Uint8 *pixel = (Uint8 *) screen->pixels;
+ int loc = 0;
+ for(int y = 0;y < height;y++) {
+ for(int x = 0;x < width;x++, pixel += bpp, loc++) {
+ if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff)
+ {
+ continue;
+ }
+ Uint32 mapped = 0;
+ switch(bpp) {
+ case 1:
+ mapped = *pixel;
+ break;
+ case 2:
+ mapped = *(Uint16 *)pixel;
+ break;
+ case 3:
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ mapped |= pixel[0] << 16;
+ mapped |= pixel[1] << 8;
+ mapped |= pixel[2] << 0;
+#else
+ mapped |= pixel[0] << 0;
+ mapped |= pixel[1] << 8;
+ mapped |= pixel[2] << 16;
+#endif
+ break;
+ case 4:
+ mapped = *(Uint32 *)pixel;
+ break;
+ }
+ Uint8 red, green, blue, alpha;
+ SDL_GetRGBA(mapped, screen->format, &red, &green, &blue, &alpha);
+ red = (red * red_channel[loc]) >> 8;
+ green = (green * green_channel[loc]) >> 8;
+ blue = (blue * blue_channel[loc]) >> 8;
+ mapped = SDL_MapRGBA(screen->format, red, green, blue, alpha);
+ switch(bpp) {
+ case 1:
+ *pixel = mapped;
+ break;
+ case 2:
+ *(Uint16 *)pixel = mapped;
+ break;
+ case 3:
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ pixel[0] = (mapped >> 16) & 0xff;
+ pixel[1] = (mapped >> 8) & 0xff;
+ pixel[2] = (mapped >> 0) & 0xff;
+#else
+ pixel[0] = (mapped >> 0) & 0xff;
+ pixel[1] = (mapped >> 8) & 0xff;
+ pixel[2] = (mapped >> 16) & 0xff;
+#endif
+ break;
+ case 4:
+ *(Uint32 *)pixel = mapped;
+ break;
+ }
+ }
+ pixel += screen->pitch - width * bpp;
+ }
+ if(SDL_MUSTLOCK(screen))
+ {
+ SDL_UnlockSurface(screen);
+ }
+ }
+ else
+ {
+ int bpp = screen->format->BytesPerPixel;
+ if(SDL_MUSTLOCK(screen))
+ {
+ SDL_LockSurface(screen);
+ }
+ Uint8 *div_pixel = (Uint8 *) screen->pixels;
+ int loc = 0;
+ for(int y = 0;y < height;y++) {
+ for(int x = 0;x < width;x++, div_pixel += bpp * LIGHTMAP_DIV, loc++) {
+ if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff)
+ {
+ continue;
+ }
+ Uint8 *pixel = div_pixel;
+ for(int div_y = 0;div_y < LIGHTMAP_DIV;div_y++) {
+ for(int div_x = 0;div_x < LIGHTMAP_DIV;pixel += bpp, div_x++) {
+ Uint32 mapped = 0;
+ switch(bpp) {
+ case 1:
+ mapped = *pixel;
+ break;
+ case 2:
+ mapped = *(Uint16 *)pixel;
+ break;
+ case 3:
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ mapped |= pixel[0] << 16;
+ mapped |= pixel[1] << 8;
+ mapped |= pixel[2] << 0;
+#else
+ mapped |= pixel[0] << 0;
+ mapped |= pixel[1] << 8;
+ mapped |= pixel[2] << 16;
+#endif
+ break;
+ case 4:
+ mapped = *(Uint32 *)pixel;
+ break;
+ }
+ Uint8 red, green, blue, alpha;
+ SDL_GetRGBA(mapped, screen->format, &red, &green, &blue, &alpha);
+
+#ifdef BILINEAR
+ int xinc = (x + 1 != width ? 1 : 0);
+ int yinc = (y + 1 != height ? width : 0);
+ Uint8 color00[3], color01[3], color10[3], color11[3];
+ {
+ color00[0] = red_channel[loc];
+ color00[1] = green_channel[loc];
+ color00[2] = blue_channel[loc];
+ }
+ {
+ color01[0] = red_channel[loc + xinc];
+ color01[1] = green_channel[loc + xinc];
+ color01[2] = blue_channel[loc + xinc];
+ }
+ {
+ color10[0] = red_channel[loc + yinc];
+ color10[1] = green_channel[loc + yinc];
+ color10[2] = blue_channel[loc + yinc];
+ }
+ {
+ color11[0] = red_channel[loc + yinc + xinc];
+ color11[1] = green_channel[loc + yinc + xinc];
+ color11[2] = blue_channel[loc + yinc + xinc];
+ }
+ Uint8 color0[3], color1[3], color[3];
+ merge(color0, color00, color01, div_x, LIGHTMAP_DIV);
+ merge(color1, color10, color11, div_x, LIGHTMAP_DIV);
+ merge(color, color0, color1, div_y, LIGHTMAP_DIV);
+ red = (red * color[0]) >> 8;
+ green = (green * color[1]) >> 8;
+ blue = (blue * color[2]) >> 8;
+#else
+ red = (red * red_channel[loc]) >> 8;
+ green = (green * green_channel[loc]) >> 8;
+ blue = (blue * blue_channel[loc]) >> 8;
+#endif
+
+ mapped = SDL_MapRGBA(screen->format, red, green, blue, alpha);
+ switch(bpp) {
+ case 1:
+ *pixel = mapped;
+ break;
+ case 2:
+ *(Uint16 *)pixel = mapped;
+ break;
+ case 3:
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ pixel[0] = (mapped >> 16) & 0xff;
+ pixel[1] = (mapped >> 8) & 0xff;
+ pixel[2] = (mapped >> 0) & 0xff;
+#else
+ pixel[0] = (mapped >> 0) & 0xff;
+ pixel[1] = (mapped >> 8) & 0xff;
+ pixel[2] = (mapped >> 16) & 0xff;
+#endif
+ break;
+ case 4:
+ *(Uint32 *)pixel = mapped;
+ break;
+ }
+ }
+ pixel += screen->pitch - LIGHTMAP_DIV * bpp;
+ }
+ }
+ div_pixel += (screen->pitch - width * bpp) * LIGHTMAP_DIV;
+ }
+ if(SDL_MUSTLOCK(screen))
+ {
+ SDL_UnlockSurface(screen);
+ }
+ }
+ }
+
+ void Lightmap::light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty)
+ {
+ dstx /= LIGHTMAP_DIV;
+ dsty /= LIGHTMAP_DIV;
+ int srcx = src_rect->x / LIGHTMAP_DIV;
+ int srcy = src_rect->y / LIGHTMAP_DIV;
+ int blit_width = src_rect->w / LIGHTMAP_DIV;
+ int blit_height = src_rect->h / LIGHTMAP_DIV;
+ int bpp = src->format->BytesPerPixel;
+ if(SDL_MUSTLOCK(src))
+ {
+ SDL_LockSurface(src);
+ }
+ Uint8 *pixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
+ int loc = dsty * width + dstx;
+ for(int y = 0;y < blit_height;y++) {
+ for(int x = 0;x < blit_width;x++, pixel += bpp * LIGHTMAP_DIV, loc++) {
+ if(x + dstx < 0 || y + dsty < 0 || x + dstx >= width || y + dsty >= height)
+ {
+ continue;
+ }
if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff)
{
continue;
}
+
Uint32 mapped = 0;
switch(bpp) {
case 1:
break;
}
Uint8 red, green, blue, alpha;
- SDL_GetRGBA(mapped, screen->format, &red, &green, &blue, &alpha);
- red = (red * red_channel[loc]) >> 8;
- green = (green * green_channel[loc]) >> 8;
- blue = (blue * blue_channel[loc]) >> 8;
- mapped = SDL_MapRGBA(screen->format, red, green, blue, alpha);
- switch(bpp) {
- case 1:
- *pixel = mapped;
- break;
- case 2:
- *(Uint16 *)pixel = mapped;
- break;
- case 3:
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- pixel[0] = (mapped >> 16) & 0xff;
- pixel[1] = (mapped >> 8) & 0xff;
- pixel[2] = (mapped >> 0) & 0xff;
-#else
- pixel[0] = (mapped >> 0) & 0xff;
- pixel[1] = (mapped >> 8) & 0xff;
- pixel[2] = (mapped >> 16) & 0xff;
-#endif
- break;
- case 4:
- *(Uint32 *)pixel = mapped;
- break;
+ SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
+
+ if(red != 0)
+ {
+ int redsum = red_channel[loc] + (red * alpha >> 8);
+ red_channel[loc] = redsum & ~0xff ? 0xff : redsum;
+ }
+ if(green != 0)
+ {
+ int greensum = green_channel[loc] + (green * alpha >> 8);
+ green_channel[loc] = greensum & ~0xff ? 0xff : greensum;
+ }
+ if(blue != 0)
+ {
+ int bluesum = blue_channel[loc] + (blue * alpha >> 8);
+ blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum;
}
}
- pixel += screen->pitch - width * bpp;
+ pixel += (src->pitch - blit_width * bpp) * LIGHTMAP_DIV;
+ loc += width - blit_width;
+ }
+ if(SDL_MUSTLOCK(src))
+ {
+ SDL_UnlockSurface(src);
}
}
- void Lightmap::light_blit(SDL_Surface *src, int dstx, int dsty,
- int srcx, int srcy, int blit_width, int blit_height)
+ /*void Lightmap::light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty)
{
int bpp = src->format->BytesPerPixel;
- Uint8 *pixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
+ if(SDL_MUSTLOCK(src))
+ {
+ SDL_LockSurface(src);
+ }
+ Uint8 *pixel = (Uint8 *) src->pixels + src_rect->y * src->pitch + src_rect->x * bpp;
int loc = dsty * width + dstx;
- for(int y = 0;y < blit_height;y++) {
- for(int x = 0;x < blit_width;x++, pixel += bpp, loc++) {
+ for(int y = 0;y < src_rect->h;y++) {
+ for(int x = 0;x < src_rect->w;x++, pixel += bpp, loc++) {
if(x + dstx < 0 || y + dsty < 0 || x + dstx >= width || y + dsty >= height)
{
continue;
blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum;
}
}
- pixel += src->pitch - blit_width * bpp;
- loc += width - blit_width;
+ pixel += src->pitch - src_rect->w * bpp;
+ loc += width - src_rect->w;
}
- }
+ if(SDL_MUSTLOCK(src))
+ {
+ SDL_UnlockSurface(src);
+ }
+ }*/
void
Lightmap::draw_surface(const DrawingRequest& request)
const Surface* surface = (const Surface*) request.request_data;
SDL::Texture *sdltexture = dynamic_cast<SDL::Texture *>(surface->get_texture());
+ SDL::SurfaceData *surface_data = reinterpret_cast<SDL::SurfaceData *>(surface->get_surface_data());
+
DrawingEffect effect = request.drawing_effect;
if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
return;
}
- int ox, oy;
- if (effect == HORIZONTAL_FLIP)
- {
- ox = sdltexture->get_texture_width() - surface->get_x() - surface->get_width();
- }
- else
- {
- ox = surface->get_x();
- }
- if (effect == VERTICAL_FLIP)
- {
- oy = sdltexture->get_texture_height() - surface->get_y() - surface->get_height();
- }
- else
- {
- oy = surface->get_y();
- }
-
- int numerator, denominator;
- float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
- float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
- if(xfactor < yfactor)
- {
- numerator = config->screenwidth;
- denominator = SCREEN_WIDTH;
- }
- else
- {
- numerator = config->screenheight;
- denominator = SCREEN_HEIGHT;
- }
-
+ SDL_Rect *src_rect = surface_data->get_src_rect(effect);
int dstx = (int) request.pos.x * numerator / denominator;
int dsty = (int) request.pos.y * numerator / denominator;
- int srcx = ox * numerator / denominator;
- int srcy = oy * numerator / denominator;
- int blit_width = surface->get_width() * numerator / denominator;
- int blit_height = surface->get_height() * numerator / denominator;
- light_blit(transform, dstx, dsty, srcx, srcy, blit_width, blit_height);
+ light_blit(transform, src_rect, dstx, dsty);
}
void
const Surface* surface = surfacepartrequest->surface;
SDL::Texture *sdltexture = dynamic_cast<SDL::Texture *>(surface->get_texture());
+
DrawingEffect effect = request.drawing_effect;
if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
oy = surface->get_y();
}
- int numerator, denominator;
- float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
- float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
- if(xfactor < yfactor)
- {
- numerator = config->screenwidth;
- denominator = SCREEN_WIDTH;
- }
- else
- {
- numerator = config->screenheight;
- denominator = SCREEN_HEIGHT;
- }
-
+ SDL_Rect src_rect;
+ src_rect.x = (ox + (int) surfacepartrequest->source.x) * numerator / denominator;
+ src_rect.y = (oy + (int) surfacepartrequest->source.y) * numerator / denominator;
+ src_rect.w = (int) surfacepartrequest->size.x * numerator / denominator;
+ src_rect.h = (int) surfacepartrequest->size.y * numerator / denominator;
int dstx = (int) request.pos.x * numerator / denominator;
int dsty = (int) request.pos.y * numerator / denominator;
- int srcx = (ox + (int) surfacepartrequest->source.x) * numerator / denominator;
- int srcy = (oy + (int) surfacepartrequest->source.y) * numerator / denominator;
- int blit_width = (int) surfacepartrequest->size.x * numerator / denominator;
- int blit_height = (int) surfacepartrequest->size.y * numerator / denominator;
- light_blit(transform, dstx, dsty, srcx, srcy, blit_width, blit_height);
+ light_blit(transform, &src_rect, dstx, dsty);
}
void
const Color& top = gradientrequest->top;
const Color& bottom = gradientrequest->bottom;
+ int loc = 0;
for(int y = 0;y < height;++y)
{
- Uint8 r = (Uint8)((((float)(top.red-bottom.red)/(0-height)) * y + top.red) * 255);
- Uint8 g = (Uint8)((((float)(top.green-bottom.green)/(0-height)) * y + top.green) * 255);
- Uint8 b = (Uint8)((((float)(top.blue-bottom.blue)/(0-height)) * y + top.blue) * 255);
- // FIXME
- //Uint8 a = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-height)) * y + top.alpha) * 255);
- for(int x = 0;x < width;x++) {
- int loc = y * width + x;
- red_channel[loc] = std::min(red_channel[loc] + r, 255);
- green_channel[loc] = std::min(green_channel[loc] + g, 255);
- blue_channel[loc] = std::min(blue_channel[loc] + b, 255);
+ Uint8 red = (Uint8)((((float)(top.red-bottom.red)/(0-height)) * y + top.red) * 255);
+ Uint8 green = (Uint8)((((float)(top.green-bottom.green)/(0-height)) * y + top.green) * 255);
+ Uint8 blue = (Uint8)((((float)(top.blue-bottom.blue)/(0-height)) * y + top.blue) * 255);
+ Uint8 alpha = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-height)) * y + top.alpha) * 255);
+ for(int x = 0;x < width;x++, loc++) {
+ if(red != 0)
+ {
+ int redsum = red_channel[loc] + (red * alpha >> 8);
+ red_channel[loc] = redsum & ~0xff ? 0xff : redsum;
+ }
+ if(green != 0)
+ {
+ int greensum = green_channel[loc] + (green * alpha >> 8);
+ green_channel[loc] = greensum & ~0xff ? 0xff : greensum;
+ }
+ if(blue != 0)
+ {
+ int bluesum = blue_channel[loc] + (blue * alpha >> 8);
+ blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum;
+ }
}
}
}
void
- Lightmap::draw_text(const DrawingRequest& /*request*/)
- {
- //const TextRequest* textrequest = (TextRequest*) request.request_data;
-
- //textrequest->font->draw(textrequest->text, request.pos,
- // textrequest->alignment, request.drawing_effect, request.alpha);
- }
-
- void
Lightmap::draw_filled_rect(const DrawingRequest& request)
{
const FillRectRequest* fillrectrequest
for(int y = rect_y;y < rect_y + rect_h;y++) {
for(int x = rect_x;x < rect_x + rect_w;x++) {
int loc = y * width + x;
- red_channel[loc] = std::min(red_channel[loc] + red, 255);
- green_channel[loc] = std::min(green_channel[loc] + green, 255);
- blue_channel[loc] = std::min(blue_channel[loc] + blue, 255);
+ if(red != 0)
+ {
+ int redsum = red_channel[loc] + red;
+ red_channel[loc] = redsum & ~0xff ? 0xff : redsum;
+ }
+ if(green != 0)
+ {
+ int greensum = green_channel[loc] + green;
+ green_channel[loc] = greensum & ~0xff ? 0xff : greensum;
+ }
+ if(blue != 0)
+ {
+ int bluesum = blue_channel[loc] + blue;
+ blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum;
+ }
}
}
}