Skip to content

Commit da02e7f

Browse files
committed
Improved performance of rect clipping
1 parent 75d3394 commit da02e7f

File tree

5 files changed

+66
-16
lines changed

5 files changed

+66
-16
lines changed

src/data_block.c

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,14 @@ populate_destinations_array(pgSurfaceObject *dest, DataBlock *block)
167167

168168
const int dest_skip = dest_surf->pitch / 4;
169169
uint32_t *dest_pixels = (uint32_t *)dest_surf->pixels;
170-
const SDL_Rect *dest_clip = &dest_surf->clip_rect;
170+
171+
const SDL_Rect dest_clip = dest_surf->clip_rect;
172+
173+
const int dst_clip_x = dest_clip.x;
174+
const int dst_clip_y = dest_clip.y;
175+
const int dst_clip_right = dest_clip.x + dest_clip.w;
176+
const int dst_clip_bottom = dest_clip.y + dest_clip.h;
177+
171178
frag_map->dest_count = 0;
172179

173180
for (int i = 0; i < frag_map->used_f; i++) {
@@ -182,14 +189,18 @@ populate_destinations_array(pgSurfaceObject *dest, DataBlock *block)
182189

183190
SDL_Surface const *src_surf = src_obj->surf;
184191
const int src_pitch = src_surf->pitch / 4;
185-
SDL_Rect src_rect = {0, 0, src_surf->w, src_surf->h};
192+
const int width = src_surf->w;
193+
const int height = src_surf->h;
186194

187195
for (int j = 0; j < length; j++) {
188-
src_rect.x = (int)positions_x[j];
189-
src_rect.y = (int)positions_y[j];
196+
const int A_x = (int)positions_x[j];
197+
const int A_y = (int)positions_y[j];
198+
const int A_x_right = A_x + width;
199+
const int A_y_bottom = A_y + height;
190200

191201
SDL_Rect clipped;
192-
if (!SDL_IntersectRect(&src_rect, dest_clip, &clipped)) {
202+
if (!IntersectRect(A_x, A_x_right, dst_clip_x, dst_clip_right, A_y,
203+
A_y_bottom, dst_clip_y, dst_clip_bottom, &clipped)) {
193204
frg->length--;
194205
continue;
195206
}
@@ -200,9 +211,8 @@ populate_destinations_array(pgSurfaceObject *dest, DataBlock *block)
200211
destination->width = clipped.w;
201212
destination->rows = clipped.h;
202213
destination->src_offset =
203-
(src_rect.x < dest_clip->x ? dest_clip->x - src_rect.x : 0) +
204-
(src_rect.y < dest_clip->y ? dest_clip->y - src_rect.y : 0) *
205-
src_pitch;
214+
(A_x < dst_clip_x ? dst_clip_x - A_x : 0) +
215+
(A_y < dst_clip_y ? dst_clip_y - A_y : 0) * src_pitch;
206216
}
207217

208218
positions_x += length;
@@ -518,7 +528,7 @@ alloc_and_init_positions(DataBlock *block, Emitter *emitter, vec2 position)
518528
float *restrict positions_y = y->data;
519529

520530
switch (emitter->spawn_shape) {
521-
case POINT:
531+
case _POINT:
522532
for (int i = 0; i < emitter->emission_number; i++) {
523533
positions_x[i] = position.x;
524534
positions_y[i] = position.y;
@@ -741,4 +751,33 @@ update_indices(DataBlock *block)
741751
#endif /* __EMSCRIPTEN__ */
742752

743753
update_indices_scalar(block);
754+
}
755+
756+
int FORCEINLINE
757+
RectEmpty(const SDL_Rect *r)
758+
{
759+
return (r->w <= 0) || (r->h <= 0);
760+
}
761+
762+
int FORCEINLINE
763+
IntersectRect(int Amin_x, int Amax_x, const int Bmin_x, const int Bmax_x, int Amin_y,
764+
int Amax_y, const int Bmin_y, const int Bmax_y, SDL_Rect *result)
765+
{
766+
/* Horizontal intersection */
767+
if (Bmin_x > Amin_x)
768+
Amin_x = Bmin_x;
769+
result->x = Amin_x;
770+
if (Bmax_x < Amax_x)
771+
Amax_x = Bmax_x;
772+
result->w = Amax_x - Amin_x;
773+
774+
/* Vertical intersection */
775+
if (Bmin_y > Amin_y)
776+
Amin_y = Bmin_y;
777+
result->y = Amin_y;
778+
if (Bmax_y < Amax_y)
779+
Amax_y = Bmax_y;
780+
result->h = Amax_y - Amin_y;
781+
782+
return !RectEmpty(result);
744783
}

src/emitter.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ emitter_init(EmitterObject *self, PyObject *args, PyObject *kwds)
141141
}
142142

143143
switch (emitter->spawn_shape) {
144-
case POINT:
144+
case _POINT:
145145
break;
146146
default:
147147
PyErr_SetString(PyExc_ValueError, "Invalid emitter spawn area shape");
@@ -324,7 +324,7 @@ emitter_str(EmitterObject *self)
324324

325325
char *spawn_shape_str;
326326
switch (e->spawn_shape) {
327-
case POINT:
327+
case _POINT:
328328
spawn_shape_str = "POINT";
329329
break;
330330
default:

src/include/data_block.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ init_fragmentation_map(DataBlock *block);
8383
void
8484
dealloc_fragmentation_map(FragmentationMap *frag_map);
8585

86+
void
87+
calculate_surface_index_occurrences(DataBlock *block);
88+
89+
int
90+
populate_destinations_array(pgSurfaceObject *dest, DataBlock *block);
91+
8692
int
8793
calculate_fragmentation_map(pgSurfaceObject *dest, DataBlock *block);
8894

@@ -136,4 +142,11 @@ recalculate_particle_count(DataBlock *block);
136142

137143
void
138144
blit_fragments_add_scalar(FragmentationMap *frag_map, PyObject **animation,
139-
int dst_skip);
145+
int dst_skip);
146+
147+
int FORCEINLINE
148+
RectEmpty(const SDL_Rect *r);
149+
150+
int FORCEINLINE
151+
IntersectRect(int Amin_x, int Amax_x, const int Bmin_x, const int Bmax_x, int Amin_y,
152+
int Amax_y, const int Bmin_y, const int Bmax_y, SDL_Rect *result);

src/include/emitter.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
#include "base.h"
66

77
typedef enum {
8-
POINT,
9-
CIRCLE,
10-
RECTANGLE,
8+
_POINT,
119
} EmitterSpawnShape;
1210

1311
typedef struct {

src/module.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ PyInit_itz_particle_manager(void)
8989
Py_INCREF(&ParticleEffect_Type);
9090
PyModule_AddObject(module, "ParticleEffect", (PyObject *)&ParticleEffect_Type);
9191

92-
if (PyModule_AddIntConstant(module, "EMIT_POINT", POINT) == -1)
92+
if (PyModule_AddIntConstant(module, "EMIT_POINT", _POINT) == -1)
9393
return NULL;
9494

9595
init_genrand((uint32_t)time(NULL));

0 commit comments

Comments
 (0)