Files
fs2open.github.com/code/scpui/RocketRenderingInterface.cpp
T
asarium e8e549ff08 Add scripting API for tracing custom code
This can be used by Lua code to trace the runtime of their code in the
same way the engine already is capable of doing for most in-mission and
mission loading code.

Also adds some tracing scopes to the libRocket code
2020-06-05 22:14:55 +02:00

259 lines
7.8 KiB
C++

//
//
// Undefine stupid windows API defines that get included by the prefix headers
#ifdef GetNextSibling
#undef GetNextSibling
#endif
#ifdef GetFirstChild
#undef GetFirstChild
#endif
// Our Assert conflicts with the definitions inside libRocket
#pragma push_macro("Assert")
#undef Assert
#include "RocketRenderingInterface.h"
#include "RocketFileInterface.h"
#pragma pop_macro("Assert")
#include "graphics/2d.h"
#include "graphics/material.h"
#include "tracing/categories.h"
#include "tracing/tracing.h"
using namespace Rocket::Core;
namespace scpui {
RocketRenderingInterface::RocketRenderingInterface()
{
renderOffset.x = 0.0f;
renderOffset.y = 0.0f;
vertex_stream_buffer = gr_create_buffer(BufferType::Vertex, BufferUsageHint::Streaming);
index_stream_buffer = gr_create_buffer(BufferType::Index, BufferUsageHint::Streaming);
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(Vertex), offsetof(Vertex, position));
layout.add_vertex_component(vertex_format_data::COLOR4, sizeof(Vertex), offsetof(Vertex, colour));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(Vertex), offsetof(Vertex, tex_coord));
}
RocketRenderingInterface::~RocketRenderingInterface()
{
if (vertex_stream_buffer >= 0) {
gr_delete_buffer(vertex_stream_buffer);
}
if (index_stream_buffer >= 0) {
gr_delete_buffer(index_stream_buffer);
}
}
RocketRenderingInterface::Texture* RocketRenderingInterface::get_texture(Rocket::Core::TextureHandle handle)
{
return reinterpret_cast<Texture*>(handle);
}
Rocket::Core::TextureHandle RocketRenderingInterface::get_texture_handle(RocketRenderingInterface::Texture* bitmap)
{
return reinterpret_cast<Rocket::Core::TextureHandle>(bitmap);
}
CompiledGeometryHandle RocketRenderingInterface::CompileGeometry(Vertex* vertices, int num_vertices, int* indices,
int num_indices, TextureHandle texture)
{
TRACE_SCOPE(tracing::RocketCompileGeometry);
GR_DEBUG_SCOPE("libRocket::CompileGeometry");
auto* geom = new CompiledGeometry();
geom->vertex_buffer = gr_create_buffer(BufferType::Vertex, BufferUsageHint::Static);
gr_update_buffer_data(geom->vertex_buffer, num_vertices * sizeof(Vertex), reinterpret_cast<void*>(vertices));
geom->index_buffer = gr_create_buffer(BufferType::Index, BufferUsageHint::Static);
gr_update_buffer_data(geom->index_buffer, num_indices * sizeof(int), reinterpret_cast<void*>(indices));
geom->num_elements = num_indices;
geom->texture = get_texture(texture);
return reinterpret_cast<CompiledGeometryHandle>(geom);
}
void RocketRenderingInterface::RenderCompiledGeometry(CompiledGeometryHandle geometry, const Vector2f& translation)
{
TRACE_SCOPE(tracing::RocketRenderCompiledGeometry);
GR_DEBUG_SCOPE("libRocket::RenderCompiledGeometry");
auto geom = reinterpret_cast<CompiledGeometry*>(geometry);
auto bitmap = -1;
if (geom->texture != nullptr) {
bitmap = geom->texture->handle + geom->texture->frame_num;
}
renderGeometry(geom->vertex_buffer, geom->index_buffer, geom->num_elements, bitmap, translation);
}
void RocketRenderingInterface::ReleaseCompiledGeometry(CompiledGeometryHandle geometry)
{
GR_DEBUG_SCOPE("libRocket::ReleaseCompiledGeometry");
auto geom = reinterpret_cast<CompiledGeometry*>(geometry);
gr_delete_buffer(geom->vertex_buffer);
gr_delete_buffer(geom->index_buffer);
delete geom;
}
void RocketRenderingInterface::EnableScissorRegion(bool enable)
{
GR_DEBUG_SCOPE("libRocket::EnableScissorRegion");
if (!enable) {
// Disable clipping if requested
gr_reset_clip();
}
// If clipping is active then SetScissorRegion will be called next
clipping_active = enable;
}
void RocketRenderingInterface::SetScissorRegion(int x, int y, int width, int height)
{
GR_DEBUG_SCOPE("libRocket::SetScissorRegion");
if (clipping_active) {
gr_set_clip((int)(x + renderOffset.x), (int)(y + renderOffset.y), width, height, GR_RESIZE_NONE);
}
}
bool RocketRenderingInterface::LoadTexture(TextureHandle& texture_handle, Vector2i& texture_dimensions,
const String& source)
{
TRACE_SCOPE(tracing::RocketLoadTexture);
GR_DEBUG_SCOPE("libRocket::LoadTexture");
SCP_string filename;
int dir_type;
if (!RocketFileInterface::getCFilePath(source, filename, dir_type)) {
return false;
}
auto period_pos = filename.rfind('.');
if (period_pos != SCP_string::npos) {
filename = filename.substr(0, period_pos);
}
auto id = bm_load_either(filename.c_str(), nullptr, nullptr, nullptr, false, dir_type);
if (id < 0) {
return false;
}
int w, h;
bm_get_info(id, &w, &h);
texture_dimensions.x = w;
texture_dimensions.y = h;
auto* tex = new Texture();
tex->handle = id;
texture_handle = get_texture_handle(tex);
return true;
}
bool RocketRenderingInterface::GenerateTexture(TextureHandle& texture_handle, const Rocket::Core::byte* source,
const Vector2i& source_dimensions)
{
TRACE_SCOPE(tracing::RocketGenerateTexture);
GR_DEBUG_SCOPE("libRocket::GenerateTexture");
auto size = (size_t)(source_dimensions.x * source_dimensions.y * 4); // RGBA format
std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]);
memcpy(buffer.get(), source, size);
auto id = bm_create(32, source_dimensions.x, source_dimensions.y, buffer.get());
if (id < 0) {
return false;
}
auto* tex = new Texture();
tex->handle = id;
tex->data = std::move(buffer);
texture_handle = get_texture_handle(tex);
return true;
}
void RocketRenderingInterface::ReleaseTexture(TextureHandle texture)
{
GR_DEBUG_SCOPE("libRocket::ReleaseTexture");
Assertion(texture, "Invalid texture handle!");
auto tex = get_texture(texture);
bm_release(tex->handle);
delete tex;
}
void RocketRenderingInterface::RenderGeometry(Vertex* vertices, int num_vertices, int* indices, int num_indices,
TextureHandle texture, const Vector2f& translation)
{
TRACE_SCOPE(tracing::RocketRenderGeometry);
GR_DEBUG_SCOPE("libRocket::RenderGeometry");
gr_update_buffer_data(vertex_stream_buffer, sizeof(*vertices) * num_vertices, vertices);
gr_update_buffer_data(index_stream_buffer, sizeof(*indices) * num_indices, indices);
int bitmap;
if (texture == 0) {
bitmap = -1;
} else {
bitmap = get_texture(texture)->handle + get_texture(texture)->frame_num;
}
renderGeometry(vertex_stream_buffer, index_stream_buffer, num_indices, bitmap, translation);
}
void RocketRenderingInterface::setRenderOffset(const vec2d& render_offset) { renderOffset = render_offset; }
float RocketRenderingInterface::GetPixelsPerInch()
{
#if SDL_VERSION_ATLEAST(2, 0, 4)
auto display = os_config_read_uint("Video", "Display", 0);
float ddpi;
if (SDL_GetDisplayDPI(display, &ddpi, nullptr, nullptr) != 0) {
mprintf(("Failed to determine display DPI: %s\n", SDL_GetError()));
return 96.f;
}
// Diagonal DPI should be accurate enough
return ddpi;
#else
// return a default value
return 96.f;
#endif
}
void RocketRenderingInterface::renderGeometry(int vertex_buffer, int index_buffer, int num_elements, int bitmap,
const Rocket::Core::Vector2f& translation)
{
interface_material material;
vec2d transl;
transl.x = translation.x + renderOffset.x;
transl.y = translation.y + renderOffset.y;
material_set_rocket_interface(&material, bitmap, transl);
gr_render_rocket_primitives(&material, PRIM_TYPE_TRIS, &layout, num_elements, vertex_buffer, index_buffer);
}
int RocketRenderingInterface::getBitmapNum(Rocket::Core::TextureHandle handle)
{
int bitmap;
if (handle == 0) {
bitmap = -1;
} else {
bitmap = get_texture(handle)->handle;
}
return bitmap;
}
void RocketRenderingInterface::setAnimationFrame(Rocket::Core::TextureHandle handle, int frame)
{
Assertion(handle != 0, "Invalid handle for setAnimationFrame");
get_texture(handle)->frame_num = frame;
}
} // namespace scpui