optimitzacions en Surface

This commit is contained in:
2026-03-31 14:56:39 +02:00
parent 2ed7316948
commit 417643018f

View File

@@ -175,12 +175,12 @@ void Surface::fillRect(const SDL_FRect* rect, Uint8 color) { // NOLINT(readabil
float x_end = std::min(rect->x + rect->w, surface_data_->width); float x_end = std::min(rect->x + rect->w, surface_data_->width);
float y_end = std::min(rect->y + rect->h, surface_data_->height); float y_end = std::min(rect->y + rect->h, surface_data_->height);
// Recorrer cada píxel dentro del rectángulo directamente // Rellenar fila a fila con memset (memoria contigua por fila)
for (int y = y_start; y < y_end; ++y) { Uint8* data_ptr = surface_data_->data.get();
for (int x = x_start; x < x_end; ++x) { const int surf_width = static_cast<int>(surface_data_->width);
const int INDEX = x + (y * surface_data_->width); const int row_width = static_cast<int>(x_end) - static_cast<int>(x_start);
surface_data_->data.get()[INDEX] = color; for (int y = static_cast<int>(y_start); y < static_cast<int>(y_end); ++y) {
} std::memset(data_ptr + (y * surf_width) + static_cast<int>(x_start), color, row_width);
} }
} }
@@ -192,16 +192,12 @@ void Surface::drawRectBorder(const SDL_FRect* rect, Uint8 color) { // NOLINT(re
float x_end = std::min(rect->x + rect->w, surface_data_->width); float x_end = std::min(rect->x + rect->w, surface_data_->width);
float y_end = std::min(rect->y + rect->h, surface_data_->height); float y_end = std::min(rect->y + rect->h, surface_data_->height);
// Dibujar bordes horizontales // Dibujar bordes horizontales con memset (líneas contiguas en memoria)
for (int x = x_start; x < x_end; ++x) { Uint8* data_ptr = surface_data_->data.get();
// Borde superior const int surf_width = static_cast<int>(surface_data_->width);
const int TOP_INDEX = x + (y_start * surface_data_->width); const int row_width = static_cast<int>(x_end) - static_cast<int>(x_start);
surface_data_->data.get()[TOP_INDEX] = color; std::memset(data_ptr + (static_cast<int>(y_start) * surf_width) + static_cast<int>(x_start), color, row_width);
std::memset(data_ptr + ((static_cast<int>(y_end) - 1) * surf_width) + static_cast<int>(x_start), color, row_width);
// Borde inferior
const int BOTTOM_INDEX = x + ((y_end - 1) * surface_data_->width);
surface_data_->data.get()[BOTTOM_INDEX] = color;
}
// Dibujar bordes verticales // Dibujar bordes verticales
for (int y = y_start; y < y_end; ++y) { for (int y = y_start; y < y_end; ++y) {
@@ -261,6 +257,8 @@ void Surface::render(float dx, float dy, float sx, float sy, float w, float h) {
w = std::min(w, surface_data->width - dx); w = std::min(w, surface_data->width - dx);
h = std::min(h, surface_data->height - dy); h = std::min(h, surface_data->height - dy);
const Uint8* src_ptr = surface_data_->data.get();
Uint8* dst_ptr = surface_data->data.get();
for (int iy = 0; iy < h; ++iy) { for (int iy = 0; iy < h; ++iy) {
for (int ix = 0; ix < w; ++ix) { for (int ix = 0; ix < w; ++ix) {
// Verificar que las coordenadas de destino están dentro de los límites // Verificar que las coordenadas de destino están dentro de los límites
@@ -269,9 +267,9 @@ void Surface::render(float dx, float dy, float sx, float sy, float w, float h) {
int src_x = sx + ix; int src_x = sx + ix;
int src_y = sy + iy; int src_y = sy + iy;
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + (src_y * surface_data_->width))]; Uint8 color = src_ptr[static_cast<size_t>(src_x + (src_y * surface_data_->width))];
if (color != static_cast<Uint8>(transparent_color_)) { if (color != static_cast<Uint8>(transparent_color_)) {
surface_data->data.get()[static_cast<size_t>(dest_x + (dest_y * surface_data->width))] = sub_palette_[color]; dst_ptr[static_cast<size_t>(dest_x + (dest_y * surface_data->width))] = sub_palette_[color];
} }
} }
} }
@@ -299,6 +297,8 @@ void Surface::render(int x, int y, SDL_FRect* src_rect, SDL_FlipMode flip) { //
h = std::min(h, surface_data_dest->height - y); h = std::min(h, surface_data_dest->height - y);
// Renderiza píxel por píxel aplicando el flip si es necesario // Renderiza píxel por píxel aplicando el flip si es necesario
const Uint8* src_ptr = surface_data_->data.get();
Uint8* dst_ptr = surface_data_dest->data.get();
for (int iy = 0; iy < h; ++iy) { for (int iy = 0; iy < h; ++iy) {
for (int ix = 0; ix < w; ++ix) { for (int ix = 0; ix < w; ++ix) {
// Coordenadas de origen // Coordenadas de origen
@@ -312,9 +312,9 @@ void Surface::render(int x, int y, SDL_FRect* src_rect, SDL_FlipMode flip) { //
// Verificar que las coordenadas de destino están dentro de los límites // Verificar que las coordenadas de destino están dentro de los límites
if (dest_x >= 0 && dest_x < surface_data_dest->width && dest_y >= 0 && dest_y < surface_data_dest->height) { if (dest_x >= 0 && dest_x < surface_data_dest->width && dest_y >= 0 && dest_y < surface_data_dest->height) {
// Copia el píxel si no es transparente // Copia el píxel si no es transparente
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + (src_y * surface_data_->width))]; Uint8 color = src_ptr[static_cast<size_t>(src_x + (src_y * surface_data_->width))];
if (color != static_cast<Uint8>(transparent_color_)) { if (color != static_cast<Uint8>(transparent_color_)) {
surface_data_dest->data[dest_x + (dest_y * surface_data_dest->width)] = sub_palette_[color]; dst_ptr[static_cast<size_t>(dest_x + (dest_y * surface_data_dest->width))] = sub_palette_[color];
} }
} }
} }
@@ -567,13 +567,16 @@ void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture) { //
// Convertir `pitch` de bytes a Uint32 (asegurando alineación correcta en hardware) // Convertir `pitch` de bytes a Uint32 (asegurando alineación correcta en hardware)
int row_stride = pitch / sizeof(Uint32); int row_stride = pitch / sizeof(Uint32);
for (int y = 0; y < surface_data_->height; ++y) { // Cachear punteros fuera del bucle para permitir autovectorización SIMD
for (int x = 0; x < surface_data_->width; ++x) { const Uint8* src = surface_data_->data.get();
// Calcular la posición correcta en la textura teniendo en cuenta el stride const Uint32* pal = palette_.data();
int texture_index = (y * row_stride) + x; const int width = surface_data_->width;
int surface_index = (y * surface_data_->width) + x; const int height = surface_data_->height;
for (int y = 0; y < height; ++y) {
pixels[texture_index] = palette_[surface_data_->data.get()[surface_index]]; const Uint8* src_row = src + (y * width);
Uint32* dst_row = pixels + (y * row_stride);
for (int x = 0; x < width; ++x) {
dst_row[x] = pal[src_row[x]];
} }
} }
@@ -613,12 +616,16 @@ void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_FR
int row_stride = pitch / sizeof(Uint32); int row_stride = pitch / sizeof(Uint32);
for (int y = 0; y < surface_data_->height; ++y) { // Cachear punteros fuera del bucle para permitir autovectorización SIMD
for (int x = 0; x < surface_data_->width; ++x) { const Uint8* src = surface_data_->data.get();
int texture_index = (y * row_stride) + x; const Uint32* pal = palette_.data();
int surface_index = (y * surface_data_->width) + x; const int width = surface_data_->width;
const int height = surface_data_->height;
pixels[texture_index] = palette_[surface_data_->data.get()[surface_index]]; for (int y = 0; y < height; ++y) {
const Uint8* src_row = src + (y * width);
Uint32* dst_row = pixels + (y * row_stride);
for (int x = 0; x < width; ++x) {
dst_row[x] = pal[src_row[x]];
} }
} }