Browse Source

TexLock

opengl-renderer-broken
Martin Dørum 4 years ago
parent
commit
cc91b3da8d

+ 1
- 0
libswan/CMakeLists.txt View File

@@ -4,6 +4,7 @@ add_library(libswan SHARED
src/Chunk.cc
src/Clock.cc
src/Game.cc
src/gfxutil.cc
src/Item.cc
src/Mod.cc
src/OS.cc

+ 4
- 4
libswan/include/swan/PerfCounter.h View File

@@ -6,13 +6,13 @@ class PerfCounter {
public:
class Counter {
public:
void count(double secs) {
latest_ = secs;
void count(double val) {
latest_ = val;
if (count_ >= 60) {
sum_ -= avg();
sum_ += secs;
sum_ += val;
} else {
sum_ += secs;
sum_ += val;
count_ += 1;
}
}

+ 16
- 0
libswan/include/swan/gfxutil.h View File

@@ -1,6 +1,8 @@
#include <SDL2/SDL.h>
#include <ostream>

#include "util.h"

namespace Swan {

inline std::ostream &operator<<(std::ostream &os, const SDL_Rect &rect) {
@@ -10,4 +12,18 @@ inline std::ostream &operator<<(std::ostream &os, const SDL_Rect &rect) {
return os;
}

class TexLock {
public:
TexLock(SDL_Texture *tex, SDL_Rect *rect = nullptr);
~TexLock();

int blit(SDL_Rect *destrect, SDL_Surface *srcsurf, SDL_Rect *srcrect = nullptr) {
return SDL_BlitSurface(srcsurf, srcrect, surf_.get(), destrect);
}

private:
SDL_Texture *tex_;
RaiiPtr<SDL_Surface> surf_ = makeRaiiPtr<SDL_Surface>(nullptr, SDL_FreeSurface);
};

}

+ 8
- 37
libswan/src/Chunk.cc View File

@@ -97,6 +97,7 @@ void Chunk::decompress() {
}

void Chunk::render(const Context &ctx) {

// The texture might not be created yet
if (!visuals_->texture_) {
visuals_->texture_.reset(SDL_CreateTexture(
@@ -104,41 +105,12 @@ void Chunk::render(const Context &ctx) {
CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE));
}

// We're caching tiles so we don't have to world.getTileByID() every time
Tile::ID prevID = Tile::INVALID_ID;
Tile *tile = ctx.game.invalid_tile_.get();

// Get info about or texture for later
uint32_t format;
int access, texw, texh;
if (SDL_QueryTexture(visuals_->texture_.get(), &format, &access, &texw, &texh) < 0) {
panic << "Failed to query texture: " << SDL_GetError();
abort();
}

// ...Now convert the format to an actually useful mask
int bpp = 32;
uint32_t rmask, gmask, bmask, amask;
if (SDL_PixelFormatEnumToMasks(format, &bpp, &rmask, &gmask, &bmask, &amask) != SDL_TRUE) {
panic << "Failed to get pixel mask: " << SDL_GetError();
abort();
}

// We lock the txture to get write access to its raw pixels
SDL_Rect rect{ 0, 0, CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE };
uint8_t *pixels;
int pitch;
if (SDL_LockTexture(visuals_->texture_.get(), &rect, (void **)&pixels, &pitch) < 0) {
panic << "Failed to lock texture: " << SDL_GetError();
abort();
}
auto lock = makeDeferred([this] { SDL_UnlockTexture(visuals_->texture_.get()); });

// This surface will refer to the pixels of our texture which we want to update.
auto destsurf = makeRaiiPtr(
SDL_CreateRGBSurfaceFrom(
pixels, TILE_SIZE, TILE_SIZE, 32, pitch,
rmask, gmask, bmask, amask),
SDL_FreeSurface);
// Locking the texture lets us write to its piexls
TexLock lock(visuals_->texture_.get());

for (int y = 0; y < CHUNK_HEIGHT; ++y) {
for (int x = 0; x < CHUNK_WIDTH; ++x) {
@@ -148,15 +120,14 @@ void Chunk::render(const Context &ctx) {
tile = &ctx.world.getTileByID(id);
}

// Find the source surface and rect...
auto &srcsurf = tile->image_.surface_;
SDL_Rect srcrect{ 0, 0, srcsurf->w, srcsurf->h };

destsurf->pixels = pixels + (y * TILE_SIZE * pitch) + x * TILE_SIZE * 4;
SDL_Rect destrect{ 0, 0, TILE_SIZE, TILE_SIZE };

if (SDL_BlitSurface(srcsurf.get(), &srcrect, destsurf.get(), &destrect) < 0) {
// ...and blit it to the appropriate place
SDL_Rect destrect{ x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE };
if (lock.blit(&destrect, srcsurf.get(), &srcrect) < 0)
warn << "Failed to blit surface: " << SDL_GetError();
}
}
}
}

+ 49
- 0
libswan/src/gfxutil.cc View File

@@ -0,0 +1,49 @@
#include "gfxutil.h"

#include <stdint.h>

#include "log.h"

namespace Swan {

TexLock::TexLock(SDL_Texture *tex, SDL_Rect *rect): tex_(tex) {

// We must query the texture to get a format...
uint32_t format;
int access, texw, texh;
if (SDL_QueryTexture(tex_, &format, &access, &texw, &texh) < 0) {
panic << "Failed to query texture: " << SDL_GetError();
abort();
}

SDL_Rect lockrect = rect == NULL
? SDL_Rect{ 0, 0, texw, texh }
: *rect;

// ...and convert that format into masks...
int bpp = 32;
uint32_t rmask, gmask, bmask, amask;
if (SDL_PixelFormatEnumToMasks(format, &bpp, &rmask, &gmask, &bmask, &amask) != SDL_TRUE) {
panic << "Failed to get pixel mask: " << SDL_GetError();
abort();
}

// ...and lock the texture...
uint8_t *pixels;
int pitch;
if (SDL_LockTexture(tex_, &lockrect, (void **)&pixels, &pitch) < 0) {
panic << "Failed to lock texture: " << SDL_GetError();
abort();
}

// ...in order to create a surface.
surf_.reset(SDL_CreateRGBSurfaceFrom(
pixels, lockrect.w, lockrect.h,
32, pitch, rmask, gmask, bmask, amask));
}

TexLock::~TexLock() {
SDL_UnlockTexture(tex_);
}

}

+ 0
- 3
libswan/src/util.cc View File

@@ -1,3 +0,0 @@
#include "util.h"

// This file is intentionally left blank.

Loading…
Cancel
Save