From 417643018f3c04afa46238706e326299e58b3c05 Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 31 Mar 2026 14:56:39 +0200 Subject: [PATCH] optimitzacions en Surface --- source/core/rendering/surface.cpp | 73 +++++++++++++++++-------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/source/core/rendering/surface.cpp b/source/core/rendering/surface.cpp index 35f820b..e3889fa 100644 --- a/source/core/rendering/surface.cpp +++ b/source/core/rendering/surface.cpp @@ -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 y_end = std::min(rect->y + rect->h, surface_data_->height); - // Recorrer cada píxel dentro del rectángulo directamente - for (int y = y_start; y < y_end; ++y) { - for (int x = x_start; x < x_end; ++x) { - const int INDEX = x + (y * surface_data_->width); - surface_data_->data.get()[INDEX] = color; - } + // Rellenar fila a fila con memset (memoria contigua por fila) + Uint8* data_ptr = surface_data_->data.get(); + const int surf_width = static_cast(surface_data_->width); + const int row_width = static_cast(x_end) - static_cast(x_start); + for (int y = static_cast(y_start); y < static_cast(y_end); ++y) { + std::memset(data_ptr + (y * surf_width) + static_cast(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 y_end = std::min(rect->y + rect->h, surface_data_->height); - // Dibujar bordes horizontales - for (int x = x_start; x < x_end; ++x) { - // Borde superior - const int TOP_INDEX = x + (y_start * surface_data_->width); - surface_data_->data.get()[TOP_INDEX] = color; - - // Borde inferior - const int BOTTOM_INDEX = x + ((y_end - 1) * surface_data_->width); - surface_data_->data.get()[BOTTOM_INDEX] = color; - } + // Dibujar bordes horizontales con memset (líneas contiguas en memoria) + Uint8* data_ptr = surface_data_->data.get(); + const int surf_width = static_cast(surface_data_->width); + const int row_width = static_cast(x_end) - static_cast(x_start); + std::memset(data_ptr + (static_cast(y_start) * surf_width) + static_cast(x_start), color, row_width); + std::memset(data_ptr + ((static_cast(y_end) - 1) * surf_width) + static_cast(x_start), color, row_width); // Dibujar bordes verticales 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); 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 ix = 0; ix < w; ++ix) { // 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_y = sy + iy; - Uint8 color = surface_data_->data.get()[static_cast(src_x + (src_y * surface_data_->width))]; + Uint8 color = src_ptr[static_cast(src_x + (src_y * surface_data_->width))]; if (color != static_cast(transparent_color_)) { - surface_data->data.get()[static_cast(dest_x + (dest_y * surface_data->width))] = sub_palette_[color]; + dst_ptr[static_cast(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); // 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 ix = 0; ix < w; ++ix) { // 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 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 - Uint8 color = surface_data_->data.get()[static_cast(src_x + (src_y * surface_data_->width))]; + Uint8 color = src_ptr[static_cast(src_x + (src_y * surface_data_->width))]; if (color != static_cast(transparent_color_)) { - surface_data_dest->data[dest_x + (dest_y * surface_data_dest->width)] = sub_palette_[color]; + dst_ptr[static_cast(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) int row_stride = pitch / sizeof(Uint32); - for (int y = 0; y < surface_data_->height; ++y) { - for (int x = 0; x < surface_data_->width; ++x) { - // Calcular la posición correcta en la textura teniendo en cuenta el stride - int texture_index = (y * row_stride) + x; - int surface_index = (y * surface_data_->width) + x; - - pixels[texture_index] = palette_[surface_data_->data.get()[surface_index]]; + // Cachear punteros fuera del bucle para permitir autovectorización SIMD + const Uint8* src = surface_data_->data.get(); + const Uint32* pal = palette_.data(); + const int width = surface_data_->width; + const int height = surface_data_->height; + 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]]; } } @@ -613,12 +616,16 @@ void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_FR int row_stride = pitch / sizeof(Uint32); - for (int y = 0; y < surface_data_->height; ++y) { - for (int x = 0; x < surface_data_->width; ++x) { - int texture_index = (y * row_stride) + x; - int surface_index = (y * surface_data_->width) + x; - - pixels[texture_index] = palette_[surface_data_->data.get()[surface_index]]; + // Cachear punteros fuera del bucle para permitir autovectorización SIMD + const Uint8* src = surface_data_->data.get(); + const Uint32* pal = palette_.data(); + const int width = surface_data_->width; + const int height = surface_data_->height; + 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]]; } }