Files
Goober5000andClaude Fable 5 a733748615 fix geometry_batcher copy semantics and add move operations
clone() allocated fresh vert/radius_list buffers without freeing the
ones already owned, so assigning over a live batcher leaked both.  It
also never copied buffer_offset, and the copy constructor called it
with no member initialization at all -- so every copy-constructed
batcher carried an uninitialized buffer_offset.  Free the existing
buffers in clone(), copy buffer_offset, and delegate the copy
constructor to the default constructor so clone() sees initialized
members (which is also what makes its new frees safe on that path).

Also add noexcept move operations, which the user-declared copy
operations had suppressed, so by-value handling can transfer the
buffers instead of deep-copying them.

None of these defects were reachable from current callers (the static
batch maps mutate entries in place); this closes the latent hazards.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-06 13:33:49 -04:00

117 lines
4.1 KiB
C++

/*
* Code created by Thomas Whittaker (RT) for a FreeSpace 2 source code project
*
* You may not sell or otherwise commercially exploit the source or things you
* created based on the source.
*
*/
#ifndef __GRBATCH_H__
#define __GRBATCH_H__
#include "2d.h"
class geometry_batcher
{
private:
int n_to_render; // the number of primitives to render
int n_allocated; // the number of verts allocated
vertex *vert;
bool use_radius;
float *radius_list; // radiuses associated with the vertices in vert
int buffer_offset;
// makes sure we have enough space in the memory buffer for the geometry we are about to put into it
// you need to figure out how many verts are going to be required
void allocate_internal(int n_verts);
void clone(const geometry_batcher &geo);
public:
geometry_batcher(): n_to_render(0), n_allocated(0), vert(NULL), use_radius(true), radius_list(NULL), buffer_offset(-1) {}
~geometry_batcher();
// delegate to the default constructor so that clone() sees initialized members
geometry_batcher(const geometry_batcher &geo) : geometry_batcher() { clone(geo); }
geometry_batcher& operator=(const geometry_batcher &geo);
geometry_batcher(geometry_batcher &&other) noexcept;
geometry_batcher& operator=(geometry_batcher &&other) noexcept;
// initial memory space needed
// NOTE: This MUST be called BEFORE calling any of the draw_*() functions!!
void allocate(int quad, int n_tri = 0);
// allocate an additional block of memory to what we already have (this is a resize function)
void add_allocate(int quad, int n_tri = 0);
// draw a bitmap into the geometry batcher
void draw_bitmap(vertex *position, int orient, float rad, float depth = 0);
// draw a rotated bitmap
void draw_bitmap(vertex *position, float rad, float angle, float depth);
// draw a simple 3 vert polygon
void draw_tri(vertex *verts);
// draw a simple 4 vert polygon
void draw_quad(vertex *verts);
// draw a beam
void draw_beam(vec3d *start, vec3d *end, float width, float intensity = 1.0f, float offset = 0.0f);
//draw a laser
float draw_laser(vec3d *p0, float width1, vec3d *p1, float width2, int r, int g, int b);
// draw all of the batched geometry to the back buffer and flushes the cache
// accepts tmap flags so you can use anything you want really
void render(int flags, float radius = 0.0f);
void load_buffer(effect_vertex* buffer, int *n_verts);
void render_buffer(gr_buffer_handle buffer_handle, int flags);
// determine if we even need to try and render this (helpful for particle system)
int need_to_render() { return n_to_render; }
};
class geometry_shader_batcher
{
SCP_vector<particle_pnt> vertices;
ptrdiff_t buffer_offset;
public:
// draw a bitmap into the geometry batcher
void draw_bitmap(vertex *position, int orient, float rad, float depth = 0);
// draw a rotated bitmap
// void draw_bitmap(vertex *position, float rad, float angle, float depth);
void load_buffer(particle_pnt* buffer, size_t *n_verts);
void render_buffer(gr_buffer_handle buffer_handle, int flags);
size_t need_to_render() { return vertices.size(); }
};
void batch_render_all(gr_buffer_handle stream_buffer = gr_buffer_handle::invalid());
void batch_render_geometry_map_bitmaps(gr_buffer_handle buffer_handle = gr_buffer_handle::invalid());
void batch_load_buffer_geometry_map_bitmaps(effect_vertex* buffer, int *n_verts);
void batch_render_lasers(gr_buffer_handle buffer_handle = gr_buffer_handle::invalid());
void batch_load_buffer_lasers(effect_vertex* buffer, int *n_verts);
void batch_reset();
void batch_render_distortion_map_bitmaps(gr_buffer_handle buffer_handle = gr_buffer_handle::invalid());
void batch_load_buffer_distortion_map_bitmaps(effect_vertex* buffer, int *n_verts);
int batch_get_size();
void batch_render_close();
int geometry_batch_add_bitmap(int texture, int tmap_flags, vertex *pnt, int orient, float rad, float alpha, float depth);
void batch_load_buffer_geometry_shader_map_bitmaps(particle_pnt* buffer, int *n_verts);
void batch_render_geometry_shader_map_bitmaps();
void geometry_batch_render(gr_buffer_handle stream_buffer);
size_t geometry_batch_get_size();
#endif