blender/intern/cycles/hydra/display_driver.cpp
Sebastian Herholz 09d2b8ae3b Cleanup: Adding global NOMINMAX compiler define for Windows builds
This PR adds the NOMINMAX define globally for the compiler when building on Windows.
This allows us to remove several NOMINMAX definitions inside the Blender code and
CMake files of various Blender submodules.

Pull Request: https://projects.blender.org/blender/blender/pulls/154255
2026-02-13 20:29:23 +01:00

292 lines
7 KiB
C++

/* SPDX-FileCopyrightText: 2022 NVIDIA Corporation
* SPDX-FileCopyrightText: 2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#ifdef _WIN32
// Include first to avoid "NOGDI" definition set in Cycles headers
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <Windows.h>
#endif
#include "hydra/display_driver.h"
#include "hydra/render_buffer.h"
#include "hydra/session.h"
#include <epoxy/gl.h>
#include <pxr/imaging/hgiGL/texture.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
HdCyclesDisplayDriver::HdCyclesDisplayDriver(HdCyclesSession *renderParam, Hgi *hgi)
: _renderParam(renderParam), _hgi(hgi)
{
}
HdCyclesDisplayDriver::~HdCyclesDisplayDriver()
{
if (texture_) {
_hgi->DestroyTexture(&texture_);
}
if (gl_pbo_id_) {
glDeleteBuffers(1, &gl_pbo_id_);
}
gl_context_dispose();
}
void HdCyclesDisplayDriver::gl_context_create()
{
#ifdef _WIN32
if (!gl_context_) {
hdc_ = GetDC(CreateWindowA("STATIC",
"HdCycles",
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0,
0,
64,
64,
nullptr,
nullptr,
GetModuleHandle(nullptr),
nullptr));
int pixelFormat = GetPixelFormat(wglGetCurrentDC());
PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd)};
DescribePixelFormat((HDC)hdc_, pixelFormat, sizeof(pfd), &pfd);
SetPixelFormat((HDC)hdc_, pixelFormat, &pfd);
TF_VERIFY(gl_context_ = wglCreateContext((HDC)hdc_));
TF_VERIFY(wglShareLists(wglGetCurrentContext(), (HGLRC)gl_context_));
}
if (!gl_context_) {
return;
}
#endif
if (!gl_pbo_id_) {
glGenBuffers(1, &gl_pbo_id_);
graphics_interop_buffer_.clear();
}
}
bool HdCyclesDisplayDriver::gl_context_enable()
{
#ifdef _WIN32
if (!hdc_ || !gl_context_) {
return false;
}
mutex_.lock();
// Do not change context if this is called in the main thread
if (wglGetCurrentContext() == nullptr) {
if (!TF_VERIFY(wglMakeCurrent((HDC)hdc_, (HGLRC)gl_context_))) {
mutex_.unlock();
return false;
}
}
return true;
#else
return false;
#endif
}
void HdCyclesDisplayDriver::gl_context_disable()
{
#ifdef _WIN32
if (wglGetCurrentContext() == gl_context_) {
TF_VERIFY(wglMakeCurrent(nullptr, nullptr));
}
mutex_.unlock();
#endif
}
void HdCyclesDisplayDriver::gl_context_dispose()
{
#ifdef _WIN32
if (gl_context_) {
TF_VERIFY(wglDeleteContext((HGLRC)gl_context_));
DestroyWindow(WindowFromDC((HDC)hdc_));
}
#endif
}
void HdCyclesDisplayDriver::next_tile_begin() {}
bool HdCyclesDisplayDriver::update_begin(const Params &params,
int /*texture_width*/,
int /*texture_height*/)
{
if (!gl_context_enable()) {
return false;
}
if (gl_render_sync_) {
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
}
if (pbo_size_.x != params.full_size.x || pbo_size_.y != params.full_size.y) {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
glBufferData(GL_PIXEL_UNPACK_BUFFER,
sizeof(half4) * params.full_size.x * params.full_size.y,
nullptr,
GL_DYNAMIC_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
pbo_size_ = params.full_size;
graphics_interop_buffer_.clear();
}
need_update_ = true;
return true;
}
void HdCyclesDisplayDriver::update_end()
{
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
gl_context_disable();
}
void HdCyclesDisplayDriver::flush()
{
gl_context_enable();
if (gl_upload_sync_) {
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
}
if (gl_render_sync_) {
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
}
gl_context_disable();
}
half4 *HdCyclesDisplayDriver::map_texture_buffer()
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
auto *const mapped_rgba_pixels = static_cast<half4 *>(
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
if (need_zero_ && mapped_rgba_pixels) {
memset(mapped_rgba_pixels, 0, sizeof(half4) * pbo_size_.x * pbo_size_.y);
need_zero_ = false;
}
return mapped_rgba_pixels;
}
void HdCyclesDisplayDriver::unmap_texture_buffer()
{
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
GraphicsInteropDevice HdCyclesDisplayDriver::graphics_interop_get_device()
{
GraphicsInteropDevice interop_device;
interop_device.type = GraphicsInteropDevice::OPENGL;
return interop_device;
}
void HdCyclesDisplayDriver::graphics_interop_update_buffer()
{
if (graphics_interop_buffer_.is_empty()) {
graphics_interop_buffer_.assign(
GraphicsInteropDevice::OPENGL, gl_pbo_id_, pbo_size_.x * pbo_size_.y * sizeof(half4));
}
if (need_zero_) {
graphics_interop_buffer_.zero();
need_zero_ = false;
}
}
void HdCyclesDisplayDriver::graphics_interop_activate()
{
gl_context_enable();
}
void HdCyclesDisplayDriver::graphics_interop_deactivate()
{
gl_context_disable();
}
void HdCyclesDisplayDriver::zero()
{
need_zero_ = true;
}
void HdCyclesDisplayDriver::draw(const Params &params)
{
auto *const renderBuffer = static_cast<HdCyclesRenderBuffer *>(
_renderParam->GetDisplayAovBinding().renderBuffer);
if (!renderBuffer || // Ensure this render buffer matches the texture dimensions
(renderBuffer->GetWidth() != params.size.x || renderBuffer->GetHeight() != params.size.y))
{
return;
}
if (!renderBuffer->IsResourceUsed()) {
return;
}
gl_context_create();
// Cycles 'DisplayDriver' only supports 'half4' format
TF_VERIFY(renderBuffer->GetFormat() == HdFormatFloat16Vec4);
const thread_scoped_lock lock(mutex_);
const GfVec3i dimensions(params.size.x, params.size.y, 1);
if (!texture_ || texture_->GetDescriptor().dimensions != dimensions) {
if (texture_) {
_hgi->DestroyTexture(&texture_);
}
HgiTextureDesc texDesc;
texDesc.usage = 0;
texDesc.format = HgiFormatFloat16Vec4;
texDesc.type = HgiTextureType2D;
texDesc.dimensions = dimensions;
texDesc.sampleCount = HgiSampleCount1;
texture_ = _hgi->CreateTexture(texDesc);
renderBuffer->SetResource(VtValue(texture_));
}
HgiGLTexture *const texture = dynamic_cast<HgiGLTexture *>(texture_.Get());
if (!texture || !need_update_ || pbo_size_.x != params.size.x || pbo_size_.y != params.size.y) {
return;
}
if (gl_upload_sync_) {
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
}
glBindTexture(GL_TEXTURE_2D, texture->GetTextureId());
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_);
glTexSubImage2D(
GL_TEXTURE_2D, 0, 0, 0, pbo_size_.x, pbo_size_.y, GL_RGBA, GL_HALF_FLOAT, nullptr);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
need_update_ = false;
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE