UI: Asset Shelf (Experimental Feature) #104831
|
@ -162,7 +162,7 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
|
|||
* \param height: The height the window.
|
||||
* \param state: The state of the window when opened.
|
||||
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
|
||||
* \param glSettings: Misc OpenGL options.
|
||||
* \param gpuSettings: Misc GPU options.
|
||||
* \return A handle to the new window ( == NULL if creation failed).
|
||||
*/
|
||||
extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
|
||||
|
@ -174,17 +174,17 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
|
|||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
bool is_dialog,
|
||||
GHOST_GLSettings glSettings);
|
||||
GHOST_GPUSettings gpuSettings);
|
||||
|
||||
/**
|
||||
* Create a new off-screen context.
|
||||
* Never explicitly delete the context, use #disposeContext() instead.
|
||||
* \param systemhandle: The handle to the system.
|
||||
* \param glSettings: Misc OpenGL options.
|
||||
* \param gpuSettings: Misc GPU options.
|
||||
* \return A handle to the new context ( == NULL if creation failed).
|
||||
*/
|
||||
extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
|
||||
GHOST_GLSettings glSettings);
|
||||
extern GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
|
||||
GHOST_GPUSettings gpuSettings);
|
||||
|
||||
/**
|
||||
* Dispose of a context.
|
||||
|
@ -192,8 +192,8 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha
|
|||
* \param contexthandle: Handle to the context to be disposed.
|
||||
* \return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
|
||||
GHOST_ContextHandle contexthandle);
|
||||
extern GHOST_TSuccess GHOST_DisposeGPUContext(GHOST_SystemHandle systemhandle,
|
||||
GHOST_ContextHandle contexthandle);
|
||||
|
||||
/**
|
||||
* Returns the window user data.
|
||||
|
@ -730,24 +730,24 @@ extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle);
|
|||
* \param contexthandle: The handle to the context.
|
||||
* \return A success indicator.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle);
|
||||
extern GHOST_TSuccess GHOST_ActivateGPUContext(GHOST_ContextHandle contexthandle);
|
||||
|
||||
/**
|
||||
* Release the drawing context bound to this thread.
|
||||
* \param contexthandle: The handle to the context.
|
||||
* \return A success indicator.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
|
||||
extern GHOST_TSuccess GHOST_ReleaseGPUContext(GHOST_ContextHandle contexthandle);
|
||||
|
||||
/**
|
||||
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
|
||||
* Get the GPU frame-buffer handle that serves as a default frame-buffer.
|
||||
*/
|
||||
extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
|
||||
extern unsigned int GHOST_GetContextDefaultGPUFramebuffer(GHOST_ContextHandle contexthandle);
|
||||
|
||||
/**
|
||||
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
|
||||
* Get the GPU frame-buffer handle that serves as a default frame-buffer.
|
||||
*/
|
||||
extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle);
|
||||
extern unsigned int GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Use multi-touch gestures if supported.
|
||||
|
@ -1072,7 +1072,7 @@ int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_context);
|
|||
|
||||
/**
|
||||
* Check if \a xr_context has a session that requires an upside-down frame-buffer (compared to
|
||||
* OpenGL). If true, the render result should be flipped vertically for correct output.
|
||||
* GPU). If true, the render result should be flipped vertically for correct output.
|
||||
* \note Only to be called after session start, may otherwise result in a false negative.
|
||||
*/
|
||||
int GHOST_XrSessionNeedsUpsideDownDrawing(const GHOST_XrContextHandle xr_context);
|
||||
|
|
|
@ -230,7 +230,7 @@ class GHOST_ISystem {
|
|||
* \param width: The width the window.
|
||||
* \param height: The height the window.
|
||||
* \param state: The state of the window when opened.
|
||||
* \param glSettings: Misc OpenGL settings.
|
||||
* \param gpuSettings: Misc GPU settings.
|
||||
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
|
||||
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
|
||||
* \param parentWindow: Parent (embedder) window
|
||||
|
@ -242,7 +242,7 @@ class GHOST_ISystem {
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive = false,
|
||||
const bool is_dialog = false,
|
||||
const GHOST_IWindow *parentWindow = NULL) = 0;
|
||||
|
@ -259,7 +259,7 @@ class GHOST_ISystem {
|
|||
* Never explicitly delete the context, use #disposeContext() instead.
|
||||
* \return The new context (or 0 if creation failed).
|
||||
*/
|
||||
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
|
||||
virtual GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) = 0;
|
||||
|
||||
/**
|
||||
* Dispose of a context.
|
||||
|
|
|
@ -64,9 +64,9 @@ typedef struct {
|
|||
} GHOST_CursorBitmapRef;
|
||||
|
||||
typedef enum {
|
||||
GHOST_glStereoVisual = (1 << 0),
|
||||
GHOST_glDebugContext = (1 << 1),
|
||||
} GHOST_GLFlags;
|
||||
GHOST_gpuStereoVisual = (1 << 0),
|
||||
GHOST_gpuDebugContext = (1 << 1),
|
||||
} GHOST_GPUFlags;
|
||||
|
||||
typedef enum GHOST_DialogOptions {
|
||||
GHOST_DialogWarning = (1 << 0),
|
||||
|
@ -681,7 +681,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
int flags;
|
||||
GHOST_TDrawingContextType context_type;
|
||||
} GHOST_GLSettings;
|
||||
} GHOST_GPUSettings;
|
||||
|
||||
typedef enum {
|
||||
/** Axis that cursor grab will wrap. */
|
||||
|
|
|
@ -135,16 +135,16 @@ void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
|
|||
system->getAllDisplayDimensions(*width, *height);
|
||||
}
|
||||
|
||||
GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
|
||||
GHOST_GLSettings glSettings)
|
||||
GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
|
||||
GHOST_GPUSettings gpuSettings)
|
||||
{
|
||||
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
|
||||
|
||||
return (GHOST_ContextHandle)system->createOffscreenContext(glSettings);
|
||||
return (GHOST_ContextHandle)system->createOffscreenContext(gpuSettings);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
|
||||
GHOST_ContextHandle contexthandle)
|
||||
GHOST_TSuccess GHOST_DisposeGPUContext(GHOST_SystemHandle systemhandle,
|
||||
GHOST_ContextHandle contexthandle)
|
||||
{
|
||||
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
|
||||
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||
|
@ -161,7 +161,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
|
|||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
bool is_dialog,
|
||||
GHOST_GLSettings glSettings)
|
||||
GHOST_GPUSettings gpuSettings)
|
||||
{
|
||||
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
|
||||
|
||||
|
@ -171,7 +171,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
|
|||
width,
|
||||
height,
|
||||
state,
|
||||
glSettings,
|
||||
gpuSettings,
|
||||
false,
|
||||
is_dialog,
|
||||
(GHOST_IWindow *)parent_windowhandle);
|
||||
|
@ -716,7 +716,7 @@ GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandl
|
|||
return window->activateDrawingContext();
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
|
||||
GHOST_TSuccess GHOST_ActivateGPUContext(GHOST_ContextHandle contexthandle)
|
||||
{
|
||||
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||
if (context) {
|
||||
|
@ -726,21 +726,21 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
|
|||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
|
||||
GHOST_TSuccess GHOST_ReleaseGPUContext(GHOST_ContextHandle contexthandle)
|
||||
{
|
||||
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||
|
||||
return context->releaseDrawingContext();
|
||||
}
|
||||
|
||||
uint GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle)
|
||||
uint GHOST_GetContextDefaultGPUFramebuffer(GHOST_ContextHandle contexthandle)
|
||||
{
|
||||
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||
|
||||
return context->getDefaultFramebuffer();
|
||||
}
|
||||
|
||||
uint GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle)
|
||||
uint GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
|
||||
|
|
|
@ -397,12 +397,12 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
|
|||
const GHOST_DisplaySetting &settings,
|
||||
const bool stereoVisual)
|
||||
{
|
||||
GHOST_GLSettings glSettings = {0};
|
||||
GHOST_GPUSettings gpuSettings = {0};
|
||||
|
||||
if (stereoVisual) {
|
||||
glSettings.flags |= GHOST_glStereoVisual;
|
||||
gpuSettings.flags |= GHOST_gpuStereoVisual;
|
||||
}
|
||||
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
|
||||
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
|
||||
/* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may
|
||||
* be zoomed in and the desktop may be bigger than the viewport. */
|
||||
GHOST_ASSERT(m_displayManager,
|
||||
|
@ -414,7 +414,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
|
|||
settings.xPixels,
|
||||
settings.yPixels,
|
||||
GHOST_kWindowStateNormal,
|
||||
glSettings,
|
||||
gpuSettings,
|
||||
true /* exclusive */);
|
||||
return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess;
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ class GHOST_System : public GHOST_ISystem {
|
|||
* Never explicitly delete the context, use #disposeContext() instead.
|
||||
* \return The new context (or 0 if creation failed).
|
||||
*/
|
||||
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
|
||||
virtual GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) = 0;
|
||||
|
||||
/**
|
||||
* Returns whether a window is valid.
|
||||
|
|
|
@ -77,7 +77,7 @@ class GHOST_SystemCocoa : public GHOST_System {
|
|||
* \param width: The width the window.
|
||||
* \param height: The height the window.
|
||||
* \param state: The state of the window when opened.
|
||||
* \param glSettings: Misc OpenGL settings.
|
||||
* \param gpuSettings: Misc GPU settings.
|
||||
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
|
||||
* \param parentWindow: Parent (embedder) window.
|
||||
* \return The new window (or 0 if creation failed).
|
||||
|
@ -88,7 +88,7 @@ class GHOST_SystemCocoa : public GHOST_System {
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive = false,
|
||||
const bool is_dialog = false,
|
||||
const GHOST_IWindow *parentWindow = NULL);
|
||||
|
@ -98,7 +98,7 @@ class GHOST_SystemCocoa : public GHOST_System {
|
|||
* Never explicitly delete the context, use #disposeContext() instead.
|
||||
* \return The new context (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings);
|
||||
|
||||
/**
|
||||
* Dispose of a context.
|
||||
|
|
|
@ -696,7 +696,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive,
|
||||
const bool is_dialog,
|
||||
const GHOST_IWindow *parentWindow)
|
||||
|
@ -725,9 +725,9 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
|
|||
width,
|
||||
height,
|
||||
state,
|
||||
glSettings.context_type,
|
||||
glSettings.flags & GHOST_glStereoVisual,
|
||||
glSettings.flags & GHOST_glDebugContext,
|
||||
gpuSettings.context_type,
|
||||
gpuSettings.flags & GHOST_gpuStereoVisual,
|
||||
gpuSettings.flags & GHOST_gpuDebugContext,
|
||||
is_dialog,
|
||||
(GHOST_WindowCocoa *)parentWindow);
|
||||
|
||||
|
@ -755,11 +755,11 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
|
|||
* Never explicitly delete the context, use #disposeContext() instead.
|
||||
* \return The new context (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
|
||||
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuSettings)
|
||||
{
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
|
||||
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
|
||||
GHOST_Context *context = new GHOST_ContextVK(false, NULL, 1, 2, debug_context);
|
||||
if (!context->initializeDrawingContext()) {
|
||||
delete context;
|
||||
|
@ -769,7 +769,7 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSet
|
|||
}
|
||||
#endif
|
||||
|
||||
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, glSettings.context_type);
|
||||
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, gpuSettings.context_type);
|
||||
if (context->initializeDrawingContext())
|
||||
return context;
|
||||
else
|
||||
|
|
|
@ -79,7 +79,7 @@ class GHOST_SystemHeadless : public GHOST_System {
|
|||
void getAllDisplayDimensions(uint32_t & /*width*/, uint32_t & /*height*/) const override
|
||||
{ /* nop */
|
||||
}
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GLSettings /*glSettings*/) override
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings /*gpuSettings*/) override
|
||||
{
|
||||
#ifdef __linux__
|
||||
GHOST_Context *context;
|
||||
|
@ -150,7 +150,7 @@ class GHOST_SystemHeadless : public GHOST_System {
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool /*exclusive*/,
|
||||
const bool /*is_dialog*/,
|
||||
const GHOST_IWindow *parentWindow) override
|
||||
|
@ -162,8 +162,8 @@ class GHOST_SystemHeadless : public GHOST_System {
|
|||
height,
|
||||
state,
|
||||
parentWindow,
|
||||
glSettings.context_type,
|
||||
((glSettings.flags & GHOST_glStereoVisual) != 0));
|
||||
gpuSettings.context_type,
|
||||
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0));
|
||||
}
|
||||
|
||||
GHOST_IWindow *getWindowUnderCursor(int32_t /*x*/, int32_t /*y*/) override
|
||||
|
|
|
@ -42,7 +42,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive,
|
||||
const bool /* is_dialog */,
|
||||
const GHOST_IWindow *parentWindow)
|
||||
|
@ -56,8 +56,8 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
|
|||
width,
|
||||
height,
|
||||
state,
|
||||
glSettings.context_type,
|
||||
((glSettings.flags & GHOST_glStereoVisual) != 0),
|
||||
gpuSettings.context_type,
|
||||
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
|
||||
exclusive,
|
||||
parentWindow);
|
||||
|
||||
|
@ -125,7 +125,7 @@ uint8_t GHOST_SystemSDL::getNumDisplays() const
|
|||
return SDL_GetNumVideoDisplays();
|
||||
}
|
||||
|
||||
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
|
||||
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GPUSettings /*gpuSettings*/)
|
||||
{
|
||||
GHOST_Context *context = new GHOST_ContextSDL(false,
|
||||
nullptr,
|
||||
|
|
|
@ -60,7 +60,7 @@ class GHOST_SystemSDL : public GHOST_System {
|
|||
|
||||
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const override;
|
||||
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
|
||||
|
||||
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
|
||||
|
||||
|
@ -73,7 +73,7 @@ class GHOST_SystemSDL : public GHOST_System {
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive = false,
|
||||
const bool is_dialog = false,
|
||||
const GHOST_IWindow *parentWindow = nullptr) override;
|
||||
|
|
|
@ -6279,7 +6279,7 @@ static GHOST_Context *createOffscreenContext_impl(GHOST_SystemWayland *system,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glSettings)
|
||||
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gpuSettings)
|
||||
{
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
std::lock_guard lock_server_guard{*server_mutex};
|
||||
|
@ -6289,9 +6289,9 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
|
|||
wl_surface *wl_surface = wl_compositor_create_surface(wl_compositor());
|
||||
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
|
||||
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
|
||||
|
||||
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
GHOST_Context *context = new GHOST_ContextVK(false,
|
||||
GHOST_kVulkanPlatformWayland,
|
||||
0,
|
||||
|
@ -6310,7 +6310,7 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
|
|||
return context;
|
||||
}
|
||||
#else
|
||||
(void)glSettings;
|
||||
(void)gpuSettings;
|
||||
#endif
|
||||
|
||||
wl_egl_window *egl_window = wl_surface ? wl_egl_window_create(wl_surface, 1, 1) : nullptr;
|
||||
|
@ -6359,7 +6359,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
|
|||
const uint32_t width,
|
||||
const uint32_t height,
|
||||
const GHOST_TWindowState state,
|
||||
const GHOST_GLSettings glSettings,
|
||||
const GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive,
|
||||
const bool is_dialog,
|
||||
const GHOST_IWindow *parentWindow)
|
||||
|
@ -6374,9 +6374,9 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
|
|||
height,
|
||||
state,
|
||||
parentWindow,
|
||||
glSettings.context_type,
|
||||
gpuSettings.context_type,
|
||||
is_dialog,
|
||||
((glSettings.flags & GHOST_glStereoVisual) != 0),
|
||||
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
|
||||
exclusive);
|
||||
|
||||
if (window) {
|
||||
|
|
|
@ -157,7 +157,7 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
|
||||
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override;
|
||||
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
|
||||
|
||||
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
|
||||
|
||||
|
@ -167,7 +167,7 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive,
|
||||
const bool is_dialog,
|
||||
const GHOST_IWindow *parentWindow) override;
|
||||
|
|
|
@ -224,7 +224,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool /*exclusive*/,
|
||||
const bool is_dialog,
|
||||
const GHOST_IWindow *parentWindow)
|
||||
|
@ -237,11 +237,11 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
|
|||
width,
|
||||
height,
|
||||
state,
|
||||
glSettings.context_type,
|
||||
((glSettings.flags & GHOST_glStereoVisual) != 0),
|
||||
gpuSettings.context_type,
|
||||
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
|
||||
false,
|
||||
(GHOST_WindowWin32 *)parentWindow,
|
||||
((glSettings.flags & GHOST_glDebugContext) != 0),
|
||||
((gpuSettings.flags & GHOST_gpuDebugContext) != 0),
|
||||
is_dialog);
|
||||
|
||||
if (window->getValid()) {
|
||||
|
@ -263,15 +263,15 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
|
|||
* Never explicitly delete the window, use #disposeContext() instead.
|
||||
* \return The new context (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GLSettings glSettings)
|
||||
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GPUSettings gpuSettings)
|
||||
{
|
||||
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
|
||||
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
|
||||
|
||||
GHOST_Context *context = nullptr;
|
||||
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
/* Vulkan does not need a window. */
|
||||
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
context = new GHOST_ContextVK(false, (HWND)0, 1, 2, debug_context);
|
||||
|
||||
if (!context->initializeDrawingContext()) {
|
||||
|
|
|
@ -103,7 +103,7 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||
* \param width: The width the window.
|
||||
* \param height: The height the window.
|
||||
* \param state: The state of the window when opened.
|
||||
* \param glSettings: Misc OpenGL settings.
|
||||
* \param gpuSettings: Misc GPU settings.
|
||||
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
|
||||
* \param parentWindow: Parent window.
|
||||
* \return The new window (or 0 if creation failed).
|
||||
|
@ -114,7 +114,7 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive = false,
|
||||
const bool is_dialog = false,
|
||||
const GHOST_IWindow *parentWindow = 0);
|
||||
|
@ -124,7 +124,7 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||
* Never explicitly delete the window, use #disposeContext() instead.
|
||||
* \return The new context (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings);
|
||||
|
||||
/**
|
||||
* Dispose of a context.
|
||||
|
|
|
@ -304,7 +304,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive,
|
||||
const bool is_dialog,
|
||||
const GHOST_IWindow *parentWindow)
|
||||
|
@ -324,11 +324,11 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
|
|||
height,
|
||||
state,
|
||||
(GHOST_WindowX11 *)parentWindow,
|
||||
glSettings.context_type,
|
||||
gpuSettings.context_type,
|
||||
is_dialog,
|
||||
((glSettings.flags & GHOST_glStereoVisual) != 0),
|
||||
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
|
||||
exclusive,
|
||||
(glSettings.flags & GHOST_glDebugContext) != 0);
|
||||
(gpuSettings.flags & GHOST_gpuDebugContext) != 0);
|
||||
|
||||
if (window) {
|
||||
/* Both are now handle in GHOST_WindowX11.cc
|
||||
|
@ -399,7 +399,7 @@ static GHOST_Context *create_glx_context(Display *display,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSettings)
|
||||
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GPUSettings gpuSettings)
|
||||
{
|
||||
/* During development:
|
||||
* try 4.x compatibility profile
|
||||
|
@ -411,11 +411,11 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
|
|||
* try 3.3 core profile
|
||||
* no fall-backs. */
|
||||
|
||||
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
|
||||
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
|
||||
GHOST_Context *context = nullptr;
|
||||
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
|
||||
context = new GHOST_ContextVK(
|
||||
false, GHOST_kVulkanPlatformX11, 0, m_display, NULL, NULL, 1, 2, debug_context);
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ class GHOST_SystemX11 : public GHOST_System {
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
GHOST_GPUSettings gpuSettings,
|
||||
const bool exclusive = false,
|
||||
const bool is_dialog = false,
|
||||
const GHOST_IWindow *parentWindow = nullptr) override;
|
||||
|
@ -134,7 +134,7 @@ class GHOST_SystemX11 : public GHOST_System {
|
|||
* Never explicitly delete the context, use #disposeContext() instead.
|
||||
* \return The new context (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
|
||||
|
||||
/**
|
||||
* Dispose of a context.
|
||||
|
|
|
@ -412,7 +412,7 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GHOST_GLSettings glSettings = {0};
|
||||
GHOST_GPUSettings gpuSettings = {0};
|
||||
char *title1 = "gears - main window";
|
||||
char *title2 = "gears - secondary window";
|
||||
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL);
|
||||
|
@ -433,7 +433,7 @@ int main(int argc, char **argv)
|
|||
GHOST_kWindowStateNormal,
|
||||
false,
|
||||
GHOST_kDrawingContextTypeOpenGL,
|
||||
glSettings);
|
||||
gpuSettings);
|
||||
if (!sMainWindow) {
|
||||
printf("could not create main window\n");
|
||||
exit(-1);
|
||||
|
@ -450,7 +450,7 @@ int main(int argc, char **argv)
|
|||
GHOST_kWindowStateNormal,
|
||||
false,
|
||||
GHOST_kDrawingContextTypeOpenGL,
|
||||
glSettings);
|
||||
gpuSettings);
|
||||
if (!sSecondaryWindow) {
|
||||
printf("could not create secondary window\n");
|
||||
exit(-1);
|
||||
|
|
|
@ -406,13 +406,13 @@ Application::Application(GHOST_ISystem *system)
|
|||
m_exitRequested(false),
|
||||
stereo(false)
|
||||
{
|
||||
GHOST_GLSettings glSettings = {0};
|
||||
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
|
||||
GHOST_GPUSettings gpuSettings = {0};
|
||||
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
|
||||
fApp = this;
|
||||
|
||||
// Create the main window
|
||||
m_mainWindow = system->createWindow(
|
||||
"gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
|
||||
"gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, gpuSettings);
|
||||
|
||||
if (!m_mainWindow) {
|
||||
std::cout << "could not create main window\n";
|
||||
|
@ -421,7 +421,7 @@ Application::Application(GHOST_ISystem *system)
|
|||
|
||||
// Create a secondary window
|
||||
m_secondaryWindow = system->createWindow(
|
||||
"gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
|
||||
"gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, gpuSettings);
|
||||
if (!m_secondaryWindow) {
|
||||
std::cout << "could not create secondary window\n";
|
||||
exit(-1);
|
||||
|
|
|
@ -306,7 +306,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
|
|||
{
|
||||
GHOST_SystemHandle sys = multitestapp_get_system(app);
|
||||
GHOST_WindowHandle win;
|
||||
GHOST_GLSettings glSettings = {0};
|
||||
GHOST_GPUSettings gpuSettings = {0};
|
||||
|
||||
win = GHOST_CreateWindow(sys,
|
||||
NULL,
|
||||
|
@ -318,7 +318,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
|
|||
GHOST_kWindowStateNormal,
|
||||
false,
|
||||
GHOST_kDrawingContextTypeOpenGL,
|
||||
glSettings);
|
||||
gpuSettings);
|
||||
|
||||
if (win) {
|
||||
MainWindow *mw = MEM_callocN(sizeof(*mw), "mainwindow_new");
|
||||
|
@ -557,7 +557,7 @@ static void loggerwindow_handle(void *priv, GHOST_EventHandle evt)
|
|||
|
||||
LoggerWindow *loggerwindow_new(MultiTestApp *app)
|
||||
{
|
||||
GHOST_GLSettings glSettings = {0};
|
||||
GHOST_GPUSettings gpuSettings = {0};
|
||||
GHOST_SystemHandle sys = multitestapp_get_system(app);
|
||||
uint32_t screensize[2];
|
||||
GHOST_WindowHandle win;
|
||||
|
@ -573,7 +573,7 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app)
|
|||
GHOST_kWindowStateNormal,
|
||||
false,
|
||||
GHOST_kDrawingContextTypeOpenGL,
|
||||
glSettings);
|
||||
gpuSettings);
|
||||
|
||||
if (win) {
|
||||
LoggerWindow *lw = MEM_callocN(sizeof(*lw), "loggerwindow_new");
|
||||
|
@ -761,7 +761,7 @@ static void extrawindow_handle(void *priv, GHOST_EventHandle evt)
|
|||
|
||||
ExtraWindow *extrawindow_new(MultiTestApp *app)
|
||||
{
|
||||
GHOST_GLSettings glSettings = {0};
|
||||
GHOST_GPUSettings gpuSettings = {0};
|
||||
GHOST_SystemHandle sys = multitestapp_get_system(app);
|
||||
GHOST_WindowHandle win;
|
||||
|
||||
|
@ -775,7 +775,7 @@ ExtraWindow *extrawindow_new(MultiTestApp *app)
|
|||
GHOST_kWindowStateNormal,
|
||||
false,
|
||||
GHOST_kDrawingContextTypeOpenGL,
|
||||
glSettings);
|
||||
gpuSettings);
|
||||
|
||||
if (win) {
|
||||
ExtraWindow *ew = MEM_callocN(sizeof(*ew), "mainwindow_new");
|
||||
|
|
|
@ -335,6 +335,7 @@ compositor_node_categories = [
|
|||
NodeItem("CompositorNodeSunBeams"),
|
||||
NodeItem("CompositorNodeDenoise"),
|
||||
NodeItem("CompositorNodeAntiAliasing"),
|
||||
NodeItem("CompositorNodeKuwahara"),
|
||||
]),
|
||||
CompositorNodeCategory("CMP_OP_VECTOR", "Vector", items=[
|
||||
NodeItem("CompositorNodeNormal"),
|
||||
|
|
|
@ -1061,6 +1061,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define CMP_NODE_INPAINT 272
|
||||
#define CMP_NODE_DESPECKLE 273
|
||||
#define CMP_NODE_ANTIALIASING 274
|
||||
#define CMP_NODE_KUWAHARA 275
|
||||
|
||||
#define CMP_NODE_GLARE 301
|
||||
#define CMP_NODE_TONEMAP 302
|
||||
|
|
|
@ -669,7 +669,7 @@ static void autotrack_context_step_cb(void *__restrict userdata,
|
|||
&libmv_reference_marker);
|
||||
}
|
||||
else {
|
||||
BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOS_FRAME);
|
||||
BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOUS_FRAME);
|
||||
autotrack_result->libmv_marker.reference_frame = libmv_current_marker->frame;
|
||||
libmv_reference_marker = *libmv_current_marker;
|
||||
}
|
||||
|
|
|
@ -322,6 +322,8 @@ if(WITH_COMPOSITOR_CPU)
|
|||
nodes/COM_FilterNode.h
|
||||
nodes/COM_InpaintNode.cc
|
||||
nodes/COM_InpaintNode.h
|
||||
nodes/COM_KuwaharaNode.h
|
||||
nodes/COM_KuwaharaNode.cc
|
||||
nodes/COM_PosterizeNode.cc
|
||||
nodes/COM_PosterizeNode.h
|
||||
|
||||
|
@ -349,6 +351,10 @@ if(WITH_COMPOSITOR_CPU)
|
|||
operations/COM_GaussianXBlurOperation.h
|
||||
operations/COM_GaussianYBlurOperation.cc
|
||||
operations/COM_GaussianYBlurOperation.h
|
||||
operations/COM_KuwaharaClassicOperation.h
|
||||
operations/COM_KuwaharaClassicOperation.cc
|
||||
operations/COM_KuwaharaAnisotropicOperation.h
|
||||
operations/COM_KuwaharaAnisotropicOperation.cc
|
||||
operations/COM_MovieClipAttributeOperation.cc
|
||||
operations/COM_MovieClipAttributeOperation.h
|
||||
operations/COM_MovieDistortionOperation.cc
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "COM_InvertNode.h"
|
||||
#include "COM_KeyingNode.h"
|
||||
#include "COM_KeyingScreenNode.h"
|
||||
#include "COM_KuwaharaNode.h"
|
||||
#include "COM_LensDistortionNode.h"
|
||||
#include "COM_LuminanceMatteNode.h"
|
||||
#include "COM_MapRangeNode.h"
|
||||
|
@ -436,6 +437,9 @@ Node *COM_convert_bnode(bNode *b_node)
|
|||
case CMP_NODE_COMBINE_XYZ:
|
||||
node = new CombineXYZNode(b_node);
|
||||
break;
|
||||
case CMP_NODE_KUWAHARA:
|
||||
node = new KuwaharaNode(b_node);
|
||||
break;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "COM_KuwaharaNode.h"
|
||||
|
||||
#include "COM_FastGaussianBlurOperation.h"
|
||||
#include "COM_KuwaharaAnisotropicOperation.h"
|
||||
#include "COM_KuwaharaClassicOperation.h"
|
||||
#include "COM_MathBaseOperation.h"
|
||||
#include "COM_SetValueOperation.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
void KuwaharaNode::convert_to_operations(NodeConverter &converter,
|
||||
const CompositorContext & /*context*/) const
|
||||
{
|
||||
const bNode *node = this->get_bnode();
|
||||
const NodeKuwaharaData *data = (const NodeKuwaharaData *)node->storage;
|
||||
|
||||
switch (data->variation) {
|
||||
case CMP_NODE_KUWAHARA_CLASSIC: {
|
||||
KuwaharaClassicOperation *operation = new KuwaharaClassicOperation();
|
||||
operation->set_kernel_size(data->size);
|
||||
|
||||
converter.add_operation(operation);
|
||||
converter.map_input_socket(get_input_socket(0), operation->get_input_socket(0));
|
||||
converter.map_output_socket(get_output_socket(0), operation->get_output_socket());
|
||||
break;
|
||||
}
|
||||
|
||||
case CMP_NODE_KUWAHARA_ANISOTROPIC: {
|
||||
/* Edge detection */
|
||||
auto const_fact = new SetValueOperation();
|
||||
const_fact->set_value(1.0f);
|
||||
converter.add_operation(const_fact);
|
||||
|
||||
auto sobel_x = new ConvolutionFilterOperation();
|
||||
sobel_x->set3x3Filter(1, 0, -1, 2, 0, -2, 1, 0, -1);
|
||||
converter.add_operation(sobel_x);
|
||||
converter.map_input_socket(get_input_socket(0), sobel_x->get_input_socket(0));
|
||||
converter.add_link(const_fact->get_output_socket(0), sobel_x->get_input_socket(1));
|
||||
|
||||
auto sobel_y = new ConvolutionFilterOperation();
|
||||
sobel_y->set3x3Filter(1, 2, 1, 0, 0, 0, -1, -2, -1);
|
||||
converter.add_operation(sobel_y);
|
||||
converter.map_input_socket(get_input_socket(0), sobel_y->get_input_socket(0));
|
||||
converter.add_link(const_fact->get_output_socket(0), sobel_y->get_input_socket(1));
|
||||
|
||||
/* Compute intensity of edges */
|
||||
auto sobel_xx = new MathMultiplyOperation();
|
||||
auto sobel_yy = new MathMultiplyOperation();
|
||||
auto sobel_xy = new MathMultiplyOperation();
|
||||
converter.add_operation(sobel_xx);
|
||||
converter.add_operation(sobel_yy);
|
||||
converter.add_operation(sobel_xy);
|
||||
|
||||
converter.add_link(sobel_x->get_output_socket(0), sobel_xx->get_input_socket(0));
|
||||
converter.add_link(sobel_x->get_output_socket(0), sobel_xx->get_input_socket(1));
|
||||
|
||||
converter.add_link(sobel_y->get_output_socket(0), sobel_yy->get_input_socket(0));
|
||||
converter.add_link(sobel_y->get_output_socket(0), sobel_yy->get_input_socket(1));
|
||||
|
||||
converter.add_link(sobel_x->get_output_socket(0), sobel_xy->get_input_socket(0));
|
||||
converter.add_link(sobel_y->get_output_socket(0), sobel_xy->get_input_socket(1));
|
||||
|
||||
/* Blurring for more robustness. */
|
||||
const int sigma = data->smoothing;
|
||||
|
||||
auto blur_sobel_xx = new FastGaussianBlurOperation();
|
||||
auto blur_sobel_yy = new FastGaussianBlurOperation();
|
||||
auto blur_sobel_xy = new FastGaussianBlurOperation();
|
||||
|
||||
blur_sobel_yy->set_size(sigma, sigma);
|
||||
blur_sobel_xx->set_size(sigma, sigma);
|
||||
blur_sobel_xy->set_size(sigma, sigma);
|
||||
|
||||
converter.add_operation(blur_sobel_xx);
|
||||
converter.add_operation(blur_sobel_yy);
|
||||
converter.add_operation(blur_sobel_xy);
|
||||
|
||||
converter.add_link(sobel_xx->get_output_socket(0), blur_sobel_xx->get_input_socket(0));
|
||||
converter.add_link(sobel_yy->get_output_socket(0), blur_sobel_yy->get_input_socket(0));
|
||||
converter.add_link(sobel_xy->get_output_socket(0), blur_sobel_xy->get_input_socket(0));
|
||||
|
||||
/* Apply anisotropic Kuwahara filter. */
|
||||
KuwaharaAnisotropicOperation *aniso = new KuwaharaAnisotropicOperation();
|
||||
aniso->set_kernel_size(data->size + 4);
|
||||
converter.map_input_socket(get_input_socket(0), aniso->get_input_socket(0));
|
||||
converter.add_operation(aniso);
|
||||
|
||||
converter.add_link(blur_sobel_xx->get_output_socket(0), aniso->get_input_socket(1));
|
||||
converter.add_link(blur_sobel_yy->get_output_socket(0), aniso->get_input_socket(2));
|
||||
converter.add_link(blur_sobel_xy->get_output_socket(0), aniso->get_input_socket(3));
|
||||
|
||||
converter.map_output_socket(get_output_socket(0), aniso->get_output_socket(0));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
|
@ -0,0 +1,23 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "COM_Node.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
/**
|
||||
* \brief KuwaharaNode
|
||||
* \ingroup Node
|
||||
*/
|
||||
|
||||
class KuwaharaNode : public Node {
|
||||
public:
|
||||
KuwaharaNode(bNode *editor_node) : Node(editor_node) {}
|
||||
void convert_to_operations(NodeConverter &converter,
|
||||
const CompositorContext &context) const override;
|
||||
};
|
||||
|
||||
} // namespace blender::compositor
|
|
@ -11,6 +11,7 @@ namespace blender::compositor {
|
|||
FastGaussianBlurOperation::FastGaussianBlurOperation() : BlurBaseOperation(DataType::Color)
|
||||
{
|
||||
iirgaus_ = nullptr;
|
||||
data_.filtertype = R_FILTER_FAST_GAUSS;
|
||||
}
|
||||
|
||||
void FastGaussianBlurOperation::execute_pixel(float output[4], int x, int y, void *data)
|
||||
|
@ -68,6 +69,15 @@ void FastGaussianBlurOperation::deinit_execution()
|
|||
BlurBaseOperation::deinit_mutex();
|
||||
}
|
||||
|
||||
void FastGaussianBlurOperation::set_size(int size_x, int size_y)
|
||||
{
|
||||
/* TODO: there should be a better way to use the operation without knowing specifics of the blur
|
||||
* node (i.e. data_). We could use factory pattern to solve this problem. */
|
||||
data_.sizex = size_x;
|
||||
data_.sizey = size_y;
|
||||
sizeavailable_ = true;
|
||||
}
|
||||
|
||||
void *FastGaussianBlurOperation::initialize_tile_data(rcti *rect)
|
||||
{
|
||||
lock_mutex();
|
||||
|
|
|
@ -28,6 +28,8 @@ class FastGaussianBlurOperation : public BlurBaseOperation {
|
|||
void deinit_execution() override;
|
||||
void init_execution() override;
|
||||
|
||||
void set_size(int size_x, int size_y);
|
||||
|
||||
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
|
||||
void update_memory_buffer_started(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
|
|
|
@ -0,0 +1,295 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "COM_KuwaharaAnisotropicOperation.h"
|
||||
|
||||
#include "BLI_math_base.hh"
|
||||
#include "BLI_vector.hh"
|
||||
#include "IMB_colormanagement.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
KuwaharaAnisotropicOperation::KuwaharaAnisotropicOperation()
|
||||
{
|
||||
this->add_input_socket(DataType::Color);
|
||||
this->add_input_socket(DataType::Color);
|
||||
this->add_input_socket(DataType::Color);
|
||||
this->add_input_socket(DataType::Color);
|
||||
|
||||
this->add_output_socket(DataType::Color);
|
||||
|
||||
this->n_div_ = 8;
|
||||
this->set_kernel_size(5);
|
||||
|
||||
this->flags_.is_fullframe_operation = true;
|
||||
}
|
||||
|
||||
void KuwaharaAnisotropicOperation::init_execution()
|
||||
{
|
||||
image_reader_ = this->get_input_socket_reader(0);
|
||||
s_xx_reader_ = this->get_input_socket_reader(1);
|
||||
s_yy_reader_ = this->get_input_socket_reader(2);
|
||||
s_xy_reader_ = this->get_input_socket_reader(3);
|
||||
}
|
||||
|
||||
void KuwaharaAnisotropicOperation::deinit_execution()
|
||||
{
|
||||
image_reader_ = nullptr;
|
||||
}
|
||||
|
||||
void KuwaharaAnisotropicOperation::execute_pixel_sampled(float output[4],
|
||||
float x,
|
||||
float y,
|
||||
PixelSampler sampler)
|
||||
{
|
||||
const int width = this->get_width();
|
||||
const int height = this->get_height();
|
||||
|
||||
BLI_assert(width == s_xx_reader_->get_width());
|
||||
BLI_assert(height == s_xx_reader_->get_height());
|
||||
BLI_assert(width == s_yy_reader_->get_width());
|
||||
BLI_assert(height == s_yy_reader_->get_height());
|
||||
BLI_assert(width == s_xy_reader_->get_width());
|
||||
BLI_assert(height == s_xy_reader_->get_height());
|
||||
|
||||
/* Values recommended by authors in original paper. */
|
||||
const float angle = 2.0 * M_PI / n_div_;
|
||||
const float q = 3.0;
|
||||
const float EPS = 1.0e-10;
|
||||
|
||||
/* For now use green channel to compute orientation. */
|
||||
/* TODO: convert to HSV and compute orientation and strength on luminance channel */
|
||||
float tmp[4];
|
||||
s_xx_reader_->read(tmp, x, y, nullptr);
|
||||
const float a = tmp[1];
|
||||
s_xy_reader_->read(tmp, x, y, nullptr);
|
||||
const float b = tmp[1];
|
||||
s_yy_reader_->read(tmp, x, y, nullptr);
|
||||
const float c = tmp[1];
|
||||
|
||||
/* Compute egenvalues of structure tensor. */
|
||||
const double tr = a + c;
|
||||
const double discr = sqrt((a - b) * (a - b) + 4 * b * c);
|
||||
const double lambda1 = (tr + discr) / 2;
|
||||
const double lambda2 = (tr - discr) / 2;
|
||||
|
||||
/* Compute orientation and its strength based on structure tensor. */
|
||||
const double orientation = 0.5 * atan2(2 * b, a - c);
|
||||
const double strength = (lambda1 == 0 && lambda2 == 0) ?
|
||||
0 :
|
||||
(lambda1 - lambda2) / (lambda1 + lambda2);
|
||||
|
||||
Vector<double> mean(n_div_);
|
||||
Vector<double> sum(n_div_);
|
||||
Vector<double> var(n_div_);
|
||||
Vector<double> weight(n_div_);
|
||||
|
||||
for (int ch = 0; ch < 3; ch++) {
|
||||
mean.fill(0.0);
|
||||
sum.fill(0.0);
|
||||
var.fill(0.0);
|
||||
weight.fill(0.0);
|
||||
|
||||
double sx = 1.0f / (strength + 1.0f);
|
||||
double sy = (1.0f + strength) / 1.0f;
|
||||
double theta = -orientation;
|
||||
|
||||
for (int dy = -kernel_size_; dy <= kernel_size_; dy++) {
|
||||
for (int dx = -kernel_size_; dx <= kernel_size_; dx++) {
|
||||
if (dx == 0 && dy == 0)
|
||||
continue;
|
||||
|
||||
/* Rotate and scale the kernel. This is the "anisotropic" part. */
|
||||
int dx2 = int(sx * (cos(theta) * dx - sin(theta) * dy));
|
||||
int dy2 = int(sy * (sin(theta) * dx + cos(theta) * dy));
|
||||
|
||||
/* Clamp image to avoid artefacts at borders. */
|
||||
const int xx = math::clamp(int(x) + dx2, 0, width - 1);
|
||||
const int yy = math::clamp(int(y) + dy2, 0, height - 1);
|
||||
|
||||
const double ddx2 = double(dx2);
|
||||
const double ddy2 = double(dy2);
|
||||
const double theta = atan2(ddy2, ddx2) + M_PI;
|
||||
const int t = int(floor(theta / angle)) % n_div_;
|
||||
double d2 = dx2 * dx2 + dy2 * dy2;
|
||||
double g = exp(-d2 / (2.0 * kernel_size_));
|
||||
float color[4];
|
||||
image_reader_->read(color, xx, yy, nullptr);
|
||||
const double v = color[ch];
|
||||
/* todo(zazizizou): only compute lum once per region */
|
||||
const float lum = IMB_colormanagement_get_luminance(color);
|
||||
/* todo(zazizizou): only compute mean for the selected region */
|
||||
mean[t] += g * v;
|
||||
sum[t] += g * lum;
|
||||
var[t] += g * lum * lum;
|
||||
weight[t] += g;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate weighted average */
|
||||
double de = 0.0;
|
||||
double nu = 0.0;
|
||||
for (int i = 0; i < n_div_; i++) {
|
||||
double weight_inv = 1.0 / weight[i];
|
||||
mean[i] = weight[i] != 0 ? mean[i] * weight_inv : 0.0;
|
||||
sum[i] = weight[i] != 0 ? sum[i] * weight_inv : 0.0;
|
||||
var[i] = weight[i] != 0 ? var[i] * weight_inv : 0.0;
|
||||
var[i] = var[i] - sum[i] * sum[i];
|
||||
var[i] = var[i] > FLT_EPSILON ? sqrt(var[i]) : FLT_EPSILON;
|
||||
double w = powf(var[i], -q);
|
||||
|
||||
de += mean[i] * w;
|
||||
nu += w;
|
||||
}
|
||||
|
||||
double val = nu > EPS ? de / nu : 0.0;
|
||||
output[ch] = val;
|
||||
}
|
||||
|
||||
/* No changes for alpha channel. */
|
||||
image_reader_->read_sampled(tmp, x, y, sampler);
|
||||
output[3] = tmp[3];
|
||||
}
|
||||
|
||||
void KuwaharaAnisotropicOperation::set_kernel_size(int kernel_size)
|
||||
{
|
||||
/* Filter will be split into n_div.
|
||||
* Add n_div / 2 to avoid artefacts such as random black pixels in image. */
|
||||
kernel_size_ = kernel_size + n_div_ / 2;
|
||||
}
|
||||
|
||||
int KuwaharaAnisotropicOperation::get_kernel_size()
|
||||
{
|
||||
return kernel_size_;
|
||||
}
|
||||
|
||||
int KuwaharaAnisotropicOperation::get_n_div()
|
||||
{
|
||||
return n_div_;
|
||||
}
|
||||
|
||||
void KuwaharaAnisotropicOperation::update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs)
|
||||
{
|
||||
/* Implementation based on Kyprianidis, Jan & Kang, Henry & Döllner, Jürgen. (2009).
|
||||
* "Image and Video Abstraction by Anisotropic Kuwahara Filtering".
|
||||
* Comput. Graph. Forum. 28. 1955-1963. 10.1111/j.1467-8659.2009.01574.x.
|
||||
* Used reference implementation from lime image processing library (MIT license). */
|
||||
|
||||
MemoryBuffer *image = inputs[0];
|
||||
MemoryBuffer *s_xx = inputs[1];
|
||||
MemoryBuffer *s_yy = inputs[2];
|
||||
MemoryBuffer *s_xy = inputs[3];
|
||||
|
||||
const int width = image->get_width();
|
||||
const int height = image->get_height();
|
||||
|
||||
BLI_assert(width == s_xx->get_width());
|
||||
BLI_assert(height == s_xx->get_height());
|
||||
BLI_assert(width == s_yy->get_width());
|
||||
BLI_assert(height == s_yy->get_height());
|
||||
BLI_assert(width == s_xy->get_width());
|
||||
BLI_assert(height == s_xy->get_height());
|
||||
|
||||
/* Values recommended by authors in original paper. */
|
||||
const float angle = 2.0 * M_PI / n_div_;
|
||||
const float q = 3.0;
|
||||
const float EPS = 1.0e-10;
|
||||
|
||||
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
|
||||
const int x = it.x;
|
||||
const int y = it.y;
|
||||
|
||||
/* For now use green channel to compute orientation. */
|
||||
/* TODO: convert to HSV and compute orientation and strength on luminance channel. */
|
||||
const float a = s_xx->get_value(x, y, 1);
|
||||
const float b = s_xy->get_value(x, y, 1);
|
||||
const float c = s_yy->get_value(x, y, 1);
|
||||
|
||||
/* Compute egenvalues of structure tensor */
|
||||
const double tr = a + c;
|
||||
const double discr = sqrt((a - b) * (a - b) + 4 * b * c);
|
||||
const double lambda1 = (tr + discr) / 2;
|
||||
const double lambda2 = (tr - discr) / 2;
|
||||
|
||||
/* Compute orientation and its strength based on structure tensor. */
|
||||
const double orientation = 0.5 * atan2(2 * b, a - c);
|
||||
const double strength = (lambda1 == 0 && lambda2 == 0) ?
|
||||
0 :
|
||||
(lambda1 - lambda2) / (lambda1 + lambda2);
|
||||
|
||||
Vector<double> mean(n_div_);
|
||||
Vector<double> sum(n_div_);
|
||||
Vector<double> var(n_div_);
|
||||
Vector<double> weight(n_div_);
|
||||
|
||||
for (int ch = 0; ch < 3; ch++) {
|
||||
mean.fill(0.0);
|
||||
sum.fill(0.0);
|
||||
var.fill(0.0);
|
||||
weight.fill(0.0);
|
||||
|
||||
double sx = 1.0f / (strength + 1.0f);
|
||||
double sy = (1.0f + strength) / 1.0f;
|
||||
double theta = -orientation;
|
||||
|
||||
for (int dy = -kernel_size_; dy <= kernel_size_; dy++) {
|
||||
for (int dx = -kernel_size_; dx <= kernel_size_; dx++) {
|
||||
if (dx == 0 && dy == 0)
|
||||
continue;
|
||||
|
||||
/* Rotate and scale the kernel. This is the "anisotropic" part. */
|
||||
int dx2 = int(sx * (cos(theta) * dx - sin(theta) * dy));
|
||||
int dy2 = int(sy * (sin(theta) * dx + cos(theta) * dy));
|
||||
|
||||
/* Clamp image to avoid artefacts at borders. */
|
||||
const int xx = math::clamp(x + dx2, 0, width - 1);
|
||||
const int yy = math::clamp(y + dy2, 0, height - 1);
|
||||
|
||||
const double ddx2 = double(dx2);
|
||||
const double ddy2 = double(dy2);
|
||||
const double theta = atan2(ddy2, ddx2) + M_PI;
|
||||
const int t = int(floor(theta / angle)) % n_div_;
|
||||
double d2 = dx2 * dx2 + dy2 * dy2;
|
||||
double g = exp(-d2 / (2.0 * kernel_size_));
|
||||
const double v = image->get_value(xx, yy, ch);
|
||||
float color[4];
|
||||
image->read_elem(xx, yy, color);
|
||||
/* TODO(zazizizou): only compute lum once per region. */
|
||||
const float lum = IMB_colormanagement_get_luminance(color);
|
||||
/* TODO(zazizizou): only compute mean for the selected region. */
|
||||
mean[t] += g * v;
|
||||
sum[t] += g * lum;
|
||||
var[t] += g * lum * lum;
|
||||
weight[t] += g;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate weighted average. */
|
||||
double de = 0.0;
|
||||
double nu = 0.0;
|
||||
for (int i = 0; i < n_div_; i++) {
|
||||
double weight_inv = 1.0 / weight[i];
|
||||
mean[i] = weight[i] != 0 ? mean[i] * weight_inv : 0.0;
|
||||
sum[i] = weight[i] != 0 ? sum[i] * weight_inv : 0.0;
|
||||
var[i] = weight[i] != 0 ? var[i] * weight_inv : 0.0;
|
||||
var[i] = var[i] - sum[i] * sum[i];
|
||||
var[i] = var[i] > FLT_EPSILON ? sqrt(var[i]) : FLT_EPSILON;
|
||||
double w = powf(var[i], -q);
|
||||
|
||||
de += mean[i] * w;
|
||||
nu += w;
|
||||
}
|
||||
|
||||
double val = nu > EPS ? de / nu : 0.0;
|
||||
it.out[ch] = val;
|
||||
}
|
||||
|
||||
/* No changes for alpha channel. */
|
||||
it.out[3] = image->get_value(x, y, 3);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
|
@ -0,0 +1,36 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "COM_MultiThreadedOperation.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
class KuwaharaAnisotropicOperation : public MultiThreadedOperation {
|
||||
SocketReader *image_reader_;
|
||||
SocketReader *s_xx_reader_;
|
||||
SocketReader *s_yy_reader_;
|
||||
SocketReader *s_xy_reader_;
|
||||
|
||||
int kernel_size_;
|
||||
int n_div_;
|
||||
|
||||
public:
|
||||
KuwaharaAnisotropicOperation();
|
||||
|
||||
void init_execution() override;
|
||||
void deinit_execution() override;
|
||||
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
void set_kernel_size(int kernel_size);
|
||||
int get_kernel_size();
|
||||
int get_n_div();
|
||||
|
||||
void update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs) override;
|
||||
};
|
||||
|
||||
} // namespace blender::compositor
|
|
@ -0,0 +1,199 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "COM_KuwaharaClassicOperation.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
KuwaharaClassicOperation::KuwaharaClassicOperation()
|
||||
{
|
||||
this->add_input_socket(DataType::Color);
|
||||
this->add_output_socket(DataType::Color);
|
||||
this->set_kernel_size(4);
|
||||
|
||||
this->flags_.is_fullframe_operation = true;
|
||||
}
|
||||
|
||||
void KuwaharaClassicOperation::init_execution()
|
||||
{
|
||||
image_reader_ = this->get_input_socket_reader(0);
|
||||
}
|
||||
|
||||
void KuwaharaClassicOperation::deinit_execution()
|
||||
{
|
||||
image_reader_ = nullptr;
|
||||
}
|
||||
|
||||
void KuwaharaClassicOperation::execute_pixel_sampled(float output[4],
|
||||
float x,
|
||||
float y,
|
||||
PixelSampler sampler)
|
||||
{
|
||||
for (int ch = 0; ch < 3; ch++) {
|
||||
float sum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float mean[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float var[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
int cnt[4] = {0, 0, 0, 0};
|
||||
|
||||
/* Split surroundings of pixel into 4 overlapping regions. */
|
||||
for (int dy = -kernel_size_; dy <= kernel_size_; dy++) {
|
||||
for (int dx = -kernel_size_; dx <= kernel_size_; dx++) {
|
||||
|
||||
int xx = x + dx;
|
||||
int yy = y + dy;
|
||||
if (xx >= 0 && yy >= 0 && xx < this->get_width() && yy < this->get_height()) {
|
||||
float color[4];
|
||||
image_reader_->read_sampled(color, xx, yy, sampler);
|
||||
const float v = color[ch];
|
||||
const float lum = IMB_colormanagement_get_luminance(color);
|
||||
|
||||
if (dx <= 0 && dy <= 0) {
|
||||
mean[0] += v;
|
||||
sum[0] += lum;
|
||||
var[0] += lum * lum;
|
||||
cnt[0]++;
|
||||
}
|
||||
|
||||
if (dx >= 0 && dy <= 0) {
|
||||
mean[1] += v;
|
||||
sum[1] += lum;
|
||||
var[1] += lum * lum;
|
||||
cnt[1]++;
|
||||
}
|
||||
|
||||
if (dx <= 0 && dy >= 0) {
|
||||
mean[2] += v;
|
||||
sum[2] += lum;
|
||||
var[2] += lum * lum;
|
||||
cnt[2]++;
|
||||
}
|
||||
|
||||
if (dx >= 0 && dy >= 0) {
|
||||
mean[3] += v;
|
||||
sum[3] += lum;
|
||||
var[3] += lum * lum;
|
||||
cnt[3]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute region variances. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mean[i] = cnt[i] != 0 ? mean[i] / cnt[i] : 0.0f;
|
||||
sum[i] = cnt[i] != 0 ? sum[i] / cnt[i] : 0.0f;
|
||||
var[i] = cnt[i] != 0 ? var[i] / cnt[i] : 0.0f;
|
||||
const float temp = sum[i] * sum[i];
|
||||
var[i] = var[i] > temp ? sqrt(var[i] - temp) : 0.0f;
|
||||
}
|
||||
|
||||
/* Choose the region with lowest variance. */
|
||||
float min_var = FLT_MAX;
|
||||
int min_index = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (var[i] < min_var) {
|
||||
min_var = var[i];
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
output[ch] = mean[min_index];
|
||||
}
|
||||
}
|
||||
|
||||
void KuwaharaClassicOperation::set_kernel_size(int kernel_size)
|
||||
{
|
||||
kernel_size_ = kernel_size;
|
||||
}
|
||||
|
||||
int KuwaharaClassicOperation::get_kernel_size()
|
||||
{
|
||||
return kernel_size_;
|
||||
}
|
||||
|
||||
void KuwaharaClassicOperation::update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs)
|
||||
{
|
||||
MemoryBuffer *image = inputs[0];
|
||||
|
||||
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
|
||||
const int x = it.x;
|
||||
const int y = it.y;
|
||||
it.out[3] = image->get_value(x, y, 3);
|
||||
|
||||
for (int ch = 0; ch < 3; ch++) {
|
||||
float sum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float mean[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float var[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
int cnt[4] = {0, 0, 0, 0};
|
||||
|
||||
/* Split surroundings of pixel into 4 overlapping regions. */
|
||||
for (int dy = -kernel_size_; dy <= kernel_size_; dy++) {
|
||||
for (int dx = -kernel_size_; dx <= kernel_size_; dx++) {
|
||||
|
||||
int xx = x + dx;
|
||||
int yy = y + dy;
|
||||
if (xx >= 0 && yy >= 0 && xx < image->get_width() && yy < image->get_height()) {
|
||||
const float v = image->get_value(xx, yy, ch);
|
||||
float color[4];
|
||||
image->read_elem(xx, yy, color);
|
||||
const float lum = IMB_colormanagement_get_luminance(color);
|
||||
|
||||
if (dx <= 0 && dy <= 0) {
|
||||
mean[0] += v;
|
||||
sum[0] += lum;
|
||||
var[0] += lum * lum;
|
||||
cnt[0]++;
|
||||
}
|
||||
|
||||
if (dx >= 0 && dy <= 0) {
|
||||
mean[1] += v;
|
||||
sum[1] += lum;
|
||||
var[1] += lum * lum;
|
||||
cnt[1]++;
|
||||
}
|
||||
|
||||
if (dx <= 0 && dy >= 0) {
|
||||
mean[2] += v;
|
||||
sum[2] += lum;
|
||||
var[2] += lum * lum;
|
||||
cnt[2]++;
|
||||
}
|
||||
|
||||
if (dx >= 0 && dy >= 0) {
|
||||
mean[3] += v;
|
||||
sum[3] += lum;
|
||||
var[3] += lum * lum;
|
||||
cnt[3]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute region variances. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mean[i] = cnt[i] != 0 ? mean[i] / cnt[i] : 0.0f;
|
||||
sum[i] = cnt[i] != 0 ? sum[i] / cnt[i] : 0.0f;
|
||||
var[i] = cnt[i] != 0 ? var[i] / cnt[i] : 0.0f;
|
||||
const float temp = sum[i] * sum[i];
|
||||
var[i] = var[i] > temp ? sqrt(var[i] - temp) : 0.0f;
|
||||
}
|
||||
|
||||
/* Choose the region with lowest variance. */
|
||||
float min_var = FLT_MAX;
|
||||
int min_index = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (var[i] < min_var) {
|
||||
min_var = var[i];
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
output->get_value(x, y, ch) = mean[min_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
|
@ -0,0 +1,31 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "COM_MultiThreadedOperation.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
class KuwaharaClassicOperation : public MultiThreadedOperation {
|
||||
SocketReader *image_reader_;
|
||||
|
||||
int kernel_size_;
|
||||
|
||||
public:
|
||||
KuwaharaClassicOperation();
|
||||
|
||||
void init_execution() override;
|
||||
void deinit_execution() override;
|
||||
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
void set_kernel_size(int kernel_size);
|
||||
int get_kernel_size();
|
||||
|
||||
void update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs) override;
|
||||
};
|
||||
|
||||
} // namespace blender::compositor
|
|
@ -152,6 +152,7 @@ set(GLSL_SRC
|
|||
shaders/compositor_smaa_edge_detection.glsl
|
||||
shaders/compositor_smaa_neighborhood_blending.glsl
|
||||
shaders/compositor_split_viewer.glsl
|
||||
shaders/compositor_sun_beams.glsl
|
||||
shaders/compositor_symmetric_blur.glsl
|
||||
shaders/compositor_symmetric_blur_variable_size.glsl
|
||||
shaders/compositor_symmetric_separable_blur.glsl
|
||||
|
@ -252,6 +253,7 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/compositor_screen_lens_distortion_info.hh
|
||||
shaders/infos/compositor_smaa_info.hh
|
||||
shaders/infos/compositor_split_viewer_info.hh
|
||||
shaders/infos/compositor_sun_beams_info.hh
|
||||
shaders/infos/compositor_symmetric_blur_info.hh
|
||||
shaders/infos/compositor_symmetric_blur_variable_size_info.hh
|
||||
shaders/infos/compositor_symmetric_separable_blur_info.hh
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 input_size = texture_size(input_tx);
|
||||
|
||||
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(input_size);
|
||||
|
||||
vec2 vector_to_source = source - coordinates;
|
||||
float distance_to_source = length(vector_to_source);
|
||||
vec2 direction_to_source = vector_to_source / distance_to_source;
|
||||
|
||||
/* We integrate from the current pixel to the source pixel, but up until the user specified
|
||||
* maximum ray length. The number of integration steps is roughly equivalent to the number of
|
||||
* pixels along the integration path. Assume a minimum number of steps of 1 to avoid zero
|
||||
* division handling and return source pixels as is. */
|
||||
float integration_length = min(distance_to_source, max_ray_length);
|
||||
float integration_length_in_pixels = length(input_size) * integration_length;
|
||||
int steps = max(1, int(integration_length_in_pixels));
|
||||
vec2 step_vector = (direction_to_source * integration_length) / steps;
|
||||
|
||||
vec4 accumulated_color = vec4(0.0);
|
||||
for (int i = 0; i < steps; i++) {
|
||||
/* Attenuate the contributions of pixels that are further away from the source using a
|
||||
* quadratic falloff. */
|
||||
float weight = pow(1.0f - i / integration_length_in_pixels, 2.0);
|
||||
accumulated_color += texture(input_tx, coordinates + i * step_vector) * weight;
|
||||
}
|
||||
|
||||
imageStore(output_img, texel, accumulated_color / steps);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_sun_beams)
|
||||
.local_group_size(16, 16)
|
||||
.push_constant(Type::VEC2, "source")
|
||||
.push_constant(Type::FLOAT, "max_ray_length")
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_sun_beams.glsl")
|
||||
.do_static_compilation(true);
|
|
@ -162,15 +162,15 @@ void DRW_uniform_attrs_pool_free(struct GHash *table);
|
|||
void DRW_render_context_enable(struct Render *render);
|
||||
void DRW_render_context_disable(struct Render *render);
|
||||
|
||||
void DRW_opengl_context_create(void);
|
||||
void DRW_opengl_context_destroy(void);
|
||||
void DRW_opengl_context_enable(void);
|
||||
void DRW_opengl_context_disable(void);
|
||||
void DRW_gpu_context_create(void);
|
||||
void DRW_gpu_context_destroy(void);
|
||||
void DRW_gpu_context_enable(void);
|
||||
void DRW_gpu_context_disable(void);
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
/* XXX: see comment on #DRW_xr_opengl_context_get() */
|
||||
void *DRW_xr_opengl_context_get(void);
|
||||
void *DRW_xr_gpu_context_get(void);
|
||||
/* XXX: see comment on #DRW_system_gpu_context_get() */
|
||||
void *DRW_system_gpu_context_get(void);
|
||||
void *DRW_xr_blender_gpu_context_get(void);
|
||||
void DRW_xr_drawing_begin(void);
|
||||
void DRW_xr_drawing_end(void);
|
||||
#endif
|
||||
|
@ -183,19 +183,16 @@ void DRW_cache_free_old_subdiv(void);
|
|||
void DRW_subdiv_free(void);
|
||||
|
||||
/* Never use this. Only for closing blender. */
|
||||
void DRW_opengl_context_enable_ex(bool restore);
|
||||
void DRW_opengl_context_disable_ex(bool restore);
|
||||
void DRW_gpu_context_enable_ex(bool restore);
|
||||
void DRW_gpu_context_disable_ex(bool restore);
|
||||
|
||||
void DRW_opengl_render_context_enable(void *re_gl_context);
|
||||
void DRW_opengl_render_context_disable(void *re_gl_context);
|
||||
/**
|
||||
* Needs to be called AFTER #DRW_opengl_render_context_enable().
|
||||
*/
|
||||
void DRW_gpu_render_context_enable(void *re_gpu_context);
|
||||
/**
|
||||
* Needs to be called BEFORE #DRW_opengl_render_context_disable().
|
||||
*/
|
||||
void DRW_gpu_render_context_disable(void *re_gpu_context);
|
||||
/* Render pipeline GPU context control.
|
||||
* Enable system context first, then enable blender context,
|
||||
* then disable blender context, then disable system context. */
|
||||
void DRW_system_gpu_render_context_enable(void *re_system_gpu_context);
|
||||
void DRW_system_gpu_render_context_disable(void *re_system_gpu_context);
|
||||
void DRW_blender_gpu_render_context_enable(void *re_gpu_context);
|
||||
void DRW_blender_gpu_render_context_disable(void *re_gpu_context);
|
||||
|
||||
void DRW_deferred_shader_remove(struct GPUMaterial *mat);
|
||||
void DRW_deferred_shader_optimize_remove(struct GPUMaterial *mat);
|
||||
|
@ -210,8 +207,8 @@ void DRW_drawdata_free(struct ID *id);
|
|||
struct DRWData *DRW_viewport_data_create(void);
|
||||
void DRW_viewport_data_free(struct DRWData *drw_data);
|
||||
|
||||
bool DRW_opengl_context_release(void);
|
||||
void DRW_opengl_context_activate(bool drw_state);
|
||||
bool DRW_gpu_context_release(void);
|
||||
void DRW_gpu_context_activate(bool drw_state);
|
||||
|
||||
/**
|
||||
* We may want to move this into a more general location.
|
||||
|
|
|
@ -62,13 +62,13 @@
|
|||
(IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_Y)
|
||||
|
||||
/* TODO: should be replace by a more elegant alternative. */
|
||||
extern void DRW_opengl_context_enable(void);
|
||||
extern void DRW_opengl_context_disable(void);
|
||||
extern void DRW_gpu_context_enable(void);
|
||||
extern void DRW_gpu_context_disable(void);
|
||||
|
||||
extern void DRW_opengl_render_context_enable(void *re_gl_context);
|
||||
extern void DRW_opengl_render_context_disable(void *re_gl_context);
|
||||
extern void DRW_gpu_render_context_enable(void *re_gpu_context);
|
||||
extern void DRW_gpu_render_context_disable(void *re_gpu_context);
|
||||
extern void DRW_system_gpu_render_context_enable(void *re_system_gpu_context);
|
||||
extern void DRW_system_gpu_render_context_disable(void *re_system_gpu_context);
|
||||
extern void DRW_blender_gpu_render_context_enable(void *re_blender_gpu_context);
|
||||
extern void DRW_blender_gpu_render_context_disable(void *re_blender_gpu_context);
|
||||
|
||||
typedef struct EEVEE_LightBake {
|
||||
Depsgraph *depsgraph;
|
||||
|
@ -157,7 +157,7 @@ typedef struct EEVEE_LightBake {
|
|||
int frame;
|
||||
|
||||
/** If running in parallel (in a separate thread), use this context. */
|
||||
void *gl_context, *gpu_context;
|
||||
void *system_gpu_context, *blender_gpu_context;
|
||||
|
||||
ThreadMutex *mutex;
|
||||
} EEVEE_LightBake;
|
||||
|
@ -601,20 +601,20 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
|
|||
{
|
||||
if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) {
|
||||
GPU_context_main_lock();
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
GPU_render_begin();
|
||||
return;
|
||||
}
|
||||
|
||||
if (lbake->gl_context) {
|
||||
DRW_opengl_render_context_enable(lbake->gl_context);
|
||||
if (lbake->gpu_context == NULL) {
|
||||
lbake->gpu_context = GPU_context_create(NULL, lbake->gl_context);
|
||||
if (lbake->system_gpu_context) {
|
||||
DRW_system_gpu_render_context_enable(lbake->system_gpu_context);
|
||||
if (lbake->blender_gpu_context == NULL) {
|
||||
lbake->blender_gpu_context = GPU_context_create(NULL, lbake->system_gpu_context);
|
||||
}
|
||||
DRW_gpu_render_context_enable(lbake->gpu_context);
|
||||
DRW_blender_gpu_render_context_enable(lbake->blender_gpu_context);
|
||||
}
|
||||
else {
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
}
|
||||
GPU_render_begin();
|
||||
}
|
||||
|
@ -623,19 +623,19 @@ static void eevee_lightbake_context_disable(EEVEE_LightBake *lbake)
|
|||
{
|
||||
|
||||
if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) {
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
GPU_render_end();
|
||||
GPU_context_main_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (lbake->gl_context) {
|
||||
DRW_gpu_render_context_disable(lbake->gpu_context);
|
||||
if (lbake->system_gpu_context) {
|
||||
DRW_blender_gpu_render_context_disable(lbake->blender_gpu_context);
|
||||
GPU_render_end();
|
||||
DRW_opengl_render_context_disable(lbake->gl_context);
|
||||
DRW_system_gpu_render_context_disable(lbake->system_gpu_context);
|
||||
}
|
||||
else {
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
GPU_render_end();
|
||||
}
|
||||
}
|
||||
|
@ -788,13 +788,13 @@ wmJob *EEVEE_lightbake_job_create(wmWindowManager *wm,
|
|||
lbake->scene = scene;
|
||||
lbake->bmain = bmain;
|
||||
lbake->view_layer_input = view_layer;
|
||||
lbake->gl_context = old_lbake->gl_context;
|
||||
lbake->system_gpu_context = old_lbake->system_gpu_context;
|
||||
lbake->own_resources = true;
|
||||
lbake->delay = delay;
|
||||
lbake->frame = frame;
|
||||
|
||||
if (lbake->gl_context == NULL && !GPU_use_main_context_workaround()) {
|
||||
lbake->gl_context = WM_opengl_context_create();
|
||||
if (lbake->system_gpu_context == NULL && !GPU_use_main_context_workaround()) {
|
||||
lbake->system_gpu_context = WM_system_gpu_context_create();
|
||||
wm_window_reset_drawable();
|
||||
}
|
||||
|
||||
|
@ -835,7 +835,7 @@ void *EEVEE_lightbake_job_data_alloc(
|
|||
lbake->frame = frame;
|
||||
|
||||
if (run_as_job && !GPU_use_main_context_workaround()) {
|
||||
lbake->gl_context = WM_opengl_context_create();
|
||||
lbake->system_gpu_context = WM_system_gpu_context_create();
|
||||
wm_window_reset_drawable();
|
||||
}
|
||||
|
||||
|
@ -865,12 +865,12 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
|
|||
BLI_mutex_lock(lbake->mutex);
|
||||
}
|
||||
|
||||
if (lbake->gl_context) {
|
||||
DRW_opengl_render_context_enable(lbake->gl_context);
|
||||
DRW_gpu_render_context_enable(lbake->gpu_context);
|
||||
if (lbake->system_gpu_context) {
|
||||
DRW_system_gpu_render_context_enable(lbake->system_gpu_context);
|
||||
DRW_blender_gpu_render_context_enable(lbake->blender_gpu_context);
|
||||
}
|
||||
else if (!lbake->resource_only) {
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
}
|
||||
|
||||
/* XXX: Free the resources contained in the view-layer data
|
||||
|
@ -887,24 +887,24 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
|
|||
GPU_FRAMEBUFFER_FREE_SAFE(lbake->rt_fb[i]);
|
||||
}
|
||||
|
||||
if (lbake->gpu_context) {
|
||||
DRW_gpu_render_context_disable(lbake->gpu_context);
|
||||
DRW_gpu_render_context_enable(lbake->gpu_context);
|
||||
GPU_context_discard(lbake->gpu_context);
|
||||
if (lbake->blender_gpu_context) {
|
||||
DRW_blender_gpu_render_context_disable(lbake->blender_gpu_context);
|
||||
DRW_blender_gpu_render_context_enable(lbake->blender_gpu_context);
|
||||
GPU_context_discard(lbake->blender_gpu_context);
|
||||
}
|
||||
|
||||
if (lbake->gl_context && lbake->own_resources) {
|
||||
if (lbake->system_gpu_context && lbake->own_resources) {
|
||||
/* Delete the baking context. */
|
||||
DRW_opengl_render_context_disable(lbake->gl_context);
|
||||
WM_opengl_context_dispose(lbake->gl_context);
|
||||
lbake->gpu_context = NULL;
|
||||
lbake->gl_context = NULL;
|
||||
DRW_system_gpu_render_context_disable(lbake->system_gpu_context);
|
||||
WM_system_gpu_context_dispose(lbake->system_gpu_context);
|
||||
lbake->blender_gpu_context = NULL;
|
||||
lbake->system_gpu_context = NULL;
|
||||
}
|
||||
else if (lbake->gl_context) {
|
||||
DRW_opengl_render_context_disable(lbake->gl_context);
|
||||
else if (lbake->system_gpu_context) {
|
||||
DRW_system_gpu_render_context_disable(lbake->system_gpu_context);
|
||||
}
|
||||
else if (!lbake->resource_only) {
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
}
|
||||
|
||||
if (!lbake->resource_only) {
|
||||
|
@ -1490,10 +1490,10 @@ void EEVEE_lightbake_job(void *custom_data, bool *stop, bool *do_update, float *
|
|||
lcache->flag |= LIGHTCACHE_BAKED;
|
||||
lcache->flag &= ~LIGHTCACHE_BAKING;
|
||||
|
||||
/* Assume that if lbake->gl_context is NULL
|
||||
/* Assume that if lbake->system_gpu_context is NULL
|
||||
* we are not running in this in a job, so update
|
||||
* the scene light-cache pointer before deleting it. */
|
||||
if (lbake->gl_context == NULL) {
|
||||
if (lbake->system_gpu_context == NULL) {
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
EEVEE_lightbake_update(lbake);
|
||||
}
|
||||
|
|
|
@ -710,7 +710,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
|
|||
|
||||
/* If light-cache auto-update is enable we tag the relevant part
|
||||
* of the cache to update and fire up a baking job. */
|
||||
if (!DRW_state_is_image_render() && !DRW_state_is_opengl_render() &&
|
||||
if (!DRW_state_is_image_render() && !DRW_state_is_viewport_image_render() &&
|
||||
(pinfo->do_grid_update || pinfo->do_cube_update))
|
||||
{
|
||||
BLI_assert(draw_ctx->evil_C);
|
||||
|
|
|
@ -94,7 +94,7 @@ void EEVEE_lookdev_init(EEVEE_Data *vedata)
|
|||
/* Viewport / Spheres size. */
|
||||
const rcti *rect;
|
||||
rcti fallback_rect;
|
||||
if (DRW_state_is_opengl_render()) {
|
||||
if (DRW_state_is_viewport_image_render()) {
|
||||
const float *vp_size = DRW_viewport_size_get();
|
||||
fallback_rect.xmax = vp_size[0];
|
||||
fallback_rect.ymax = vp_size[1];
|
||||
|
|
|
@ -431,7 +431,7 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
|
|||
|
||||
bool is_valid = (render_pass & EEVEE_RENDERPASSES_ALL) != 0;
|
||||
bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) != 0 &&
|
||||
DRW_state_is_opengl_render();
|
||||
DRW_state_is_viewport_image_render();
|
||||
UNUSED_VARS(needs_color_transfer);
|
||||
|
||||
if ((render_pass & EEVEE_RENDER_PASS_BLOOM) != 0 &&
|
||||
|
|
|
@ -245,7 +245,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
|
|||
* Reset for each "redraw". When rendering using OpenGL render,
|
||||
* we accumulate the redraw inside the drawing loop in eevee_draw_scene().
|
||||
*/
|
||||
if (DRW_state_is_opengl_render()) {
|
||||
if (DRW_state_is_viewport_image_render()) {
|
||||
effects->taa_render_sample = 1;
|
||||
}
|
||||
effects->bypass_drawing = false;
|
||||
|
|
|
@ -11,6 +11,11 @@ shared float zdists_cache[gl_WorkGroupSize.x];
|
|||
|
||||
void main()
|
||||
{
|
||||
/* Early exit if no lights are present to prevent out of bounds buffer read. */
|
||||
if (light_cull_buf.visible_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint src_index = gl_GlobalInvocationID.x;
|
||||
bool valid_thread = true;
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ void main()
|
|||
tile.is_used = true;
|
||||
}
|
||||
/* Reset count for next level. */
|
||||
usage_grid[tile_co.y][tile_co.x] = 0u;
|
||||
usage_grid[tile_co.y / 2][tile_co.x / 2] = 0u;
|
||||
}
|
||||
|
||||
barrier();
|
||||
|
|
|
@ -57,7 +57,8 @@ void main()
|
|||
|
||||
ivec2 tile_co = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 tile_shifted = tile_co + tilemap.grid_shift;
|
||||
ivec2 tile_wrapped = ivec2(tile_shifted % SHADOW_TILEMAP_RES);
|
||||
/* Ensure value is shifted into positive range to avoid modulo on negative. */
|
||||
ivec2 tile_wrapped = ivec2((ivec2(SHADOW_TILEMAP_RES) + tile_shifted) % SHADOW_TILEMAP_RES);
|
||||
|
||||
/* If this tile was shifted in and contains old information, update it.
|
||||
* Note that cubemap always shift all tiles on update. */
|
||||
|
@ -72,7 +73,7 @@ void main()
|
|||
uint lod_size = uint(SHADOW_TILEMAP_RES);
|
||||
for (int lod = 0; lod <= lod_max; lod++, lod_size >>= 1u) {
|
||||
bool thread_active = all(lessThan(tile_co, ivec2(lod_size)));
|
||||
ShadowTileDataPacked tile;
|
||||
ShadowTileDataPacked tile = 0;
|
||||
int tile_load = shadow_tile_offset(tile_wrapped, tilemap.tiles_index, lod);
|
||||
if (thread_active) {
|
||||
tile = init_tile_data(tiles_buf[tile_load], do_update);
|
||||
|
|
|
@ -30,7 +30,7 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
|
|||
float color_override[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
int background_type;
|
||||
|
||||
if (DRW_state_is_opengl_render() && !DRW_state_draw_background()) {
|
||||
if (DRW_state_is_viewport_image_render() && !DRW_state_draw_background()) {
|
||||
background_type = BG_SOLID;
|
||||
color_override[3] = 1.0f;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class Background {
|
|||
float4 color_override(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
int background_type;
|
||||
|
||||
if (DRW_state_is_opengl_render() && !DRW_state_draw_background()) {
|
||||
if (DRW_state_is_viewport_image_render() && !DRW_state_draw_background()) {
|
||||
background_type = BG_SOLID;
|
||||
color_override[3] = 1.0f;
|
||||
}
|
||||
|
|
|
@ -630,7 +630,7 @@ static void workbench_draw_scene(void *ved)
|
|||
WORKBENCH_Data *vedata = ved;
|
||||
WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
|
||||
|
||||
if (DRW_state_is_opengl_render()) {
|
||||
if (DRW_state_is_viewport_image_render()) {
|
||||
while (wpd->taa_sample < max_ii(1, wpd->taa_sample_len)) {
|
||||
workbench_update_world_ubo(wpd);
|
||||
|
||||
|
|
|
@ -944,7 +944,7 @@ bool DRW_state_is_scene_render(void);
|
|||
/**
|
||||
* Whether we are rendering simple opengl render
|
||||
*/
|
||||
bool DRW_state_is_opengl_render(void);
|
||||
bool DRW_state_is_viewport_image_render(void);
|
||||
bool DRW_state_is_playback(void);
|
||||
/**
|
||||
* Is the user navigating the region.
|
||||
|
|
|
@ -61,7 +61,7 @@ BLI_INLINE void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo)
|
|||
BLI_INLINE bool DRW_ibo_requested(GPUIndexBuf *ibo)
|
||||
{
|
||||
/* TODO: do not rely on data uploaded. This prevents multi-threading.
|
||||
* (need access to a OpenGL context). */
|
||||
* (need access to a GPU context). */
|
||||
return (ibo != NULL && !GPU_indexbuf_is_init(ibo));
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ static struct {
|
|||
|
||||
static void drw_state_prepare_clean_for_draw(DRWManager *dst)
|
||||
{
|
||||
memset(dst, 0x0, offsetof(DRWManager, gl_context));
|
||||
memset(dst, 0x0, offsetof(DRWManager, system_gpu_context));
|
||||
}
|
||||
|
||||
/* This function is used to reset draw manager to a state
|
||||
|
@ -126,7 +126,7 @@ static void drw_state_prepare_clean_for_draw(DRWManager *dst)
|
|||
#ifdef DEBUG
|
||||
static void drw_state_ensure_not_reused(DRWManager *dst)
|
||||
{
|
||||
memset(dst, 0xff, offsetof(DRWManager, gl_context));
|
||||
memset(dst, 0xff, offsetof(DRWManager, system_gpu_context));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1341,7 +1341,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
|
|||
/* XXX Really nasty locking. But else this could
|
||||
* be executed by the material previews thread
|
||||
* while rendering a viewport. */
|
||||
BLI_ticket_mutex_lock(DST.gl_context_mutex);
|
||||
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
|
||||
|
||||
/* Reset before using it. */
|
||||
drw_state_prepare_clean_for_draw(&DST);
|
||||
|
@ -1378,7 +1378,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
|
|||
|
||||
drw_manager_exit(&DST);
|
||||
|
||||
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
|
||||
BLI_ticket_mutex_unlock(DST.system_gpu_context_mutex);
|
||||
}
|
||||
|
||||
/* update a viewport which belongs to a GPUOffscreen */
|
||||
|
@ -1905,7 +1905,7 @@ static void DRW_render_gpencil_to_image(RenderEngine *engine,
|
|||
void DRW_render_gpencil(RenderEngine *engine, Depsgraph *depsgraph)
|
||||
{
|
||||
/* This function should only be called if there are grease pencil objects,
|
||||
* especially important to avoid failing in background renders without OpenGL context. */
|
||||
* especially important to avoid failing in background renders without GPU context. */
|
||||
BLI_assert(DRW_render_check_grease_pencil(depsgraph));
|
||||
|
||||
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||
|
@ -2964,7 +2964,7 @@ bool DRW_state_is_scene_render(void)
|
|||
return DST.options.is_scene_render;
|
||||
}
|
||||
|
||||
bool DRW_state_is_opengl_render(void)
|
||||
bool DRW_state_is_viewport_image_render(void)
|
||||
{
|
||||
return DST.options.is_image_render && !DST.options.is_scene_render;
|
||||
}
|
||||
|
@ -3119,14 +3119,14 @@ void DRW_engines_free(void)
|
|||
{
|
||||
drw_registered_engines_free();
|
||||
|
||||
if (DST.gl_context == NULL) {
|
||||
if (DST.system_gpu_context == NULL) {
|
||||
/* Nothing has been setup. Nothing to clear.
|
||||
* Otherwise, DRW_opengl_context_enable can
|
||||
* Otherwise, DRW_gpu_context_enable can
|
||||
* create a context in background mode. (see #62355) */
|
||||
return;
|
||||
}
|
||||
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
|
||||
DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
|
||||
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
|
||||
|
@ -3152,59 +3152,59 @@ void DRW_engines_free(void)
|
|||
GPU_draw_list_discard(DST.draw_list);
|
||||
}
|
||||
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
}
|
||||
|
||||
void DRW_render_context_enable(Render *render)
|
||||
{
|
||||
if (G.background && DST.gl_context == NULL) {
|
||||
WM_init_opengl();
|
||||
if (G.background && DST.system_gpu_context == NULL) {
|
||||
WM_init_gpu();
|
||||
}
|
||||
|
||||
GPU_render_begin();
|
||||
|
||||
if (GPU_use_main_context_workaround()) {
|
||||
GPU_context_main_lock();
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
return;
|
||||
}
|
||||
|
||||
void *re_gl_context = RE_gl_context_get(render);
|
||||
void *re_system_gpu_context = RE_system_gpu_context_get(render);
|
||||
|
||||
/* Changing Context */
|
||||
if (re_gl_context != NULL) {
|
||||
DRW_opengl_render_context_enable(re_gl_context);
|
||||
if (re_system_gpu_context != NULL) {
|
||||
DRW_system_gpu_render_context_enable(re_system_gpu_context);
|
||||
/* We need to query gpu context after a gl context has been bound. */
|
||||
void *re_gpu_context = NULL;
|
||||
re_gpu_context = RE_gpu_context_get(render);
|
||||
DRW_gpu_render_context_enable(re_gpu_context);
|
||||
void *re_blender_gpu_context = NULL;
|
||||
re_blender_gpu_context = RE_blender_gpu_context_get(render);
|
||||
DRW_blender_gpu_render_context_enable(re_blender_gpu_context);
|
||||
}
|
||||
else {
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
}
|
||||
}
|
||||
|
||||
void DRW_render_context_disable(Render *render)
|
||||
{
|
||||
if (GPU_use_main_context_workaround()) {
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
GPU_render_end();
|
||||
GPU_context_main_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
void *re_gl_context = RE_gl_context_get(render);
|
||||
void *re_system_gpu_context = RE_system_gpu_context_get(render);
|
||||
|
||||
if (re_gl_context != NULL) {
|
||||
void *re_gpu_context = NULL;
|
||||
re_gpu_context = RE_gpu_context_get(render);
|
||||
if (re_system_gpu_context != NULL) {
|
||||
void *re_blender_gpu_context = NULL;
|
||||
re_blender_gpu_context = RE_blender_gpu_context_get(render);
|
||||
/* GPU rendering may occur during context disable. */
|
||||
DRW_gpu_render_context_disable(re_gpu_context);
|
||||
DRW_blender_gpu_render_context_disable(re_blender_gpu_context);
|
||||
GPU_render_end();
|
||||
DRW_opengl_render_context_disable(re_gl_context);
|
||||
DRW_system_gpu_render_context_disable(re_system_gpu_context);
|
||||
}
|
||||
else {
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
GPU_render_end();
|
||||
}
|
||||
}
|
||||
|
@ -3212,51 +3212,51 @@ void DRW_render_context_disable(Render *render)
|
|||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Init/Exit (DRW_opengl_ctx)
|
||||
/** \name Init/Exit (DRW_gpu_ctx)
|
||||
* \{ */
|
||||
|
||||
void DRW_opengl_context_create(void)
|
||||
void DRW_gpu_context_create(void)
|
||||
{
|
||||
BLI_assert(DST.gl_context == NULL); /* Ensure it's called once */
|
||||
BLI_assert(DST.system_gpu_context == NULL); /* Ensure it's called once */
|
||||
|
||||
DST.gl_context_mutex = BLI_ticket_mutex_alloc();
|
||||
DST.system_gpu_context_mutex = BLI_ticket_mutex_alloc();
|
||||
/* This changes the active context. */
|
||||
DST.gl_context = WM_opengl_context_create();
|
||||
WM_opengl_context_activate(DST.gl_context);
|
||||
/* Be sure to create gpu_context too. */
|
||||
DST.gpu_context = GPU_context_create(0, DST.gl_context);
|
||||
DST.system_gpu_context = WM_system_gpu_context_create();
|
||||
WM_system_gpu_context_activate(DST.system_gpu_context);
|
||||
/* Be sure to create blender_gpu_context too. */
|
||||
DST.blender_gpu_context = GPU_context_create(0, DST.system_gpu_context);
|
||||
/* So we activate the window's one afterwards. */
|
||||
wm_window_reset_drawable();
|
||||
}
|
||||
|
||||
void DRW_opengl_context_destroy(void)
|
||||
void DRW_gpu_context_destroy(void)
|
||||
{
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
if (DST.gl_context != NULL) {
|
||||
WM_opengl_context_activate(DST.gl_context);
|
||||
GPU_context_active_set(DST.gpu_context);
|
||||
GPU_context_discard(DST.gpu_context);
|
||||
WM_opengl_context_dispose(DST.gl_context);
|
||||
BLI_ticket_mutex_free(DST.gl_context_mutex);
|
||||
if (DST.system_gpu_context != NULL) {
|
||||
WM_system_gpu_context_activate(DST.system_gpu_context);
|
||||
GPU_context_active_set(DST.blender_gpu_context);
|
||||
GPU_context_discard(DST.blender_gpu_context);
|
||||
WM_system_gpu_context_dispose(DST.system_gpu_context);
|
||||
BLI_ticket_mutex_free(DST.system_gpu_context_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void DRW_opengl_context_enable_ex(bool UNUSED(restore))
|
||||
void DRW_gpu_context_enable_ex(bool UNUSED(restore))
|
||||
{
|
||||
if (DST.gl_context != NULL) {
|
||||
if (DST.system_gpu_context != NULL) {
|
||||
/* IMPORTANT: We don't support immediate mode in render mode!
|
||||
* This shall remain in effect until immediate mode supports
|
||||
* multiple threads. */
|
||||
BLI_ticket_mutex_lock(DST.gl_context_mutex);
|
||||
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
|
||||
GPU_render_begin();
|
||||
WM_opengl_context_activate(DST.gl_context);
|
||||
GPU_context_active_set(DST.gpu_context);
|
||||
WM_system_gpu_context_activate(DST.system_gpu_context);
|
||||
GPU_context_active_set(DST.blender_gpu_context);
|
||||
}
|
||||
}
|
||||
|
||||
void DRW_opengl_context_disable_ex(bool restore)
|
||||
void DRW_gpu_context_disable_ex(bool restore)
|
||||
{
|
||||
if (DST.gl_context != NULL) {
|
||||
if (DST.system_gpu_context != NULL) {
|
||||
#ifdef __APPLE__
|
||||
/* Need to flush before disabling draw context, otherwise it does not
|
||||
* always finish drawing and viewport can be empty or partially drawn */
|
||||
|
@ -3269,7 +3269,7 @@ void DRW_opengl_context_disable_ex(bool restore)
|
|||
wm_window_reset_drawable();
|
||||
}
|
||||
else {
|
||||
WM_opengl_context_release(DST.gl_context);
|
||||
WM_system_gpu_context_release(DST.system_gpu_context);
|
||||
GPU_context_active_set(NULL);
|
||||
}
|
||||
|
||||
|
@ -3277,51 +3277,51 @@ void DRW_opengl_context_disable_ex(bool restore)
|
|||
* called outside of an existing render loop. */
|
||||
GPU_render_end();
|
||||
|
||||
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
|
||||
BLI_ticket_mutex_unlock(DST.system_gpu_context_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void DRW_opengl_context_enable(void)
|
||||
void DRW_gpu_context_enable(void)
|
||||
{
|
||||
/* TODO: should be replace by a more elegant alternative. */
|
||||
|
||||
if (G.background && DST.gl_context == NULL) {
|
||||
WM_init_opengl();
|
||||
if (G.background && DST.system_gpu_context == NULL) {
|
||||
WM_init_gpu();
|
||||
}
|
||||
DRW_opengl_context_enable_ex(true);
|
||||
DRW_gpu_context_enable_ex(true);
|
||||
}
|
||||
|
||||
void DRW_opengl_context_disable(void)
|
||||
void DRW_gpu_context_disable(void)
|
||||
{
|
||||
DRW_opengl_context_disable_ex(true);
|
||||
DRW_gpu_context_disable_ex(true);
|
||||
}
|
||||
|
||||
void DRW_opengl_render_context_enable(void *re_gl_context)
|
||||
void DRW_system_gpu_render_context_enable(void *re_system_gpu_context)
|
||||
{
|
||||
/* If thread is main you should use DRW_opengl_context_enable(). */
|
||||
/* If thread is main you should use DRW_gpu_context_enable(). */
|
||||
BLI_assert(!BLI_thread_is_main());
|
||||
|
||||
/* TODO: get rid of the blocking. Only here because of the static global DST. */
|
||||
BLI_ticket_mutex_lock(DST.gl_context_mutex);
|
||||
WM_opengl_context_activate(re_gl_context);
|
||||
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
|
||||
WM_system_gpu_context_activate(re_system_gpu_context);
|
||||
}
|
||||
|
||||
void DRW_opengl_render_context_disable(void *re_gl_context)
|
||||
void DRW_system_gpu_render_context_disable(void *re_system_gpu_context)
|
||||
{
|
||||
WM_opengl_context_release(re_gl_context);
|
||||
WM_system_gpu_context_release(re_system_gpu_context);
|
||||
/* TODO: get rid of the blocking. */
|
||||
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
|
||||
BLI_ticket_mutex_unlock(DST.system_gpu_context_mutex);
|
||||
}
|
||||
|
||||
void DRW_gpu_render_context_enable(void *re_gpu_context)
|
||||
void DRW_blender_gpu_render_context_enable(void *re_gpu_context)
|
||||
{
|
||||
/* If thread is main you should use DRW_opengl_context_enable(). */
|
||||
/* If thread is main you should use DRW_gpu_context_enable(). */
|
||||
BLI_assert(!BLI_thread_is_main());
|
||||
|
||||
GPU_context_active_set(re_gpu_context);
|
||||
}
|
||||
|
||||
void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context))
|
||||
void DRW_blender_gpu_render_context_disable(void *UNUSED(re_gpu_context))
|
||||
{
|
||||
GPU_flush();
|
||||
GPU_context_active_set(NULL);
|
||||
|
@ -3331,39 +3331,39 @@ void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context))
|
|||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
|
||||
void *DRW_xr_opengl_context_get(void)
|
||||
void *DRW_system_gpu_context_get(void)
|
||||
{
|
||||
/* XXX: There should really be no such getter, but for VR we currently can't easily avoid it.
|
||||
* OpenXR needs some low level info for the OpenGL context that will be used for submitting the
|
||||
* OpenXR needs some low level info for the GPU context that will be used for submitting the
|
||||
* final frame-buffer. VR could in theory create its own context, but that would mean we have to
|
||||
* switch to it just to submit the final frame, which has notable performance impact.
|
||||
*
|
||||
* We could "inject" a context through DRW_opengl_render_context_enable(), but that would have to
|
||||
* work from the main thread, which is tricky to get working too. The preferable solution would
|
||||
* be using a separate thread for VR drawing where a single context can stay active. */
|
||||
* We could "inject" a context through DRW_system_gpu_render_context_enable(), but that would
|
||||
* have to work from the main thread, which is tricky to get working too. The preferable solution
|
||||
* would be using a separate thread for VR drawing where a single context can stay active. */
|
||||
|
||||
return DST.gl_context;
|
||||
return DST.system_gpu_context;
|
||||
}
|
||||
|
||||
void *DRW_xr_gpu_context_get(void)
|
||||
void *DRW_xr_blender_gpu_context_get(void)
|
||||
{
|
||||
/* XXX: See comment on #DRW_xr_opengl_context_get(). */
|
||||
/* XXX: See comment on #DRW_system_gpu_context_get(). */
|
||||
|
||||
return DST.gpu_context;
|
||||
return DST.blender_gpu_context;
|
||||
}
|
||||
|
||||
void DRW_xr_drawing_begin(void)
|
||||
{
|
||||
/* XXX: See comment on #DRW_xr_opengl_context_get(). */
|
||||
/* XXX: See comment on #DRW_system_gpu_context_get(). */
|
||||
|
||||
BLI_ticket_mutex_lock(DST.gl_context_mutex);
|
||||
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
|
||||
}
|
||||
|
||||
void DRW_xr_drawing_end(void)
|
||||
{
|
||||
/* XXX: See comment on #DRW_xr_opengl_context_get(). */
|
||||
/* XXX: See comment on #DRW_system_gpu_context_get(). */
|
||||
|
||||
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
|
||||
BLI_ticket_mutex_unlock(DST.system_gpu_context_mutex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -3388,58 +3388,59 @@ void DRW_draw_state_init_gtests(eGPUShaderConfig sh_cfg)
|
|||
/* -------------------------------------------------------------------- */
|
||||
/** \name Draw manager context release/activation
|
||||
*
|
||||
* These functions are used in cases when an OpenGL context creation is needed during the draw.
|
||||
* This happens, for example, when an external engine needs to create its own OpenGL context from
|
||||
* These functions are used in cases when an GPU context creation is needed during the draw.
|
||||
* This happens, for example, when an external engine needs to create its own GPU context from
|
||||
* the engine initialization.
|
||||
*
|
||||
* Example of context creation:
|
||||
*
|
||||
* const bool drw_state = DRW_opengl_context_release();
|
||||
* gl_context = WM_opengl_context_create();
|
||||
* DRW_opengl_context_activate(drw_state);
|
||||
* const bool drw_state = DRW_gpu_context_release();
|
||||
* system_gpu_context = WM_system_gpu_context_create();
|
||||
* DRW_gpu_context_activate(drw_state);
|
||||
*
|
||||
* Example of context destruction:
|
||||
*
|
||||
* const bool drw_state = DRW_opengl_context_release();
|
||||
* WM_opengl_context_activate(gl_context);
|
||||
* WM_opengl_context_dispose(gl_context);
|
||||
* DRW_opengl_context_activate(drw_state);
|
||||
* const bool drw_state = DRW_gpu_context_release();
|
||||
* WM_system_gpu_context_activate(system_gpu_context);
|
||||
* WM_system_gpu_context_dispose(system_gpu_context);
|
||||
* DRW_gpu_context_activate(drw_state);
|
||||
*
|
||||
*
|
||||
* NOTE: Will only perform context modification when on main thread. This way these functions can
|
||||
* be used in an engine without check on whether it is a draw manager which manages OpenGL context
|
||||
* on the current thread. The downside of this is that if the engine performs OpenGL creation from
|
||||
* a non-main thread, that thread is supposed to not have OpenGL context ever bound by Blender.
|
||||
* be used in an engine without check on whether it is a draw manager which manages GPU context
|
||||
* on the current thread. The downside of this is that if the engine performs GPU creation from
|
||||
* a non-main thread, that thread is supposed to not have GPU context ever bound by Blender.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
bool DRW_opengl_context_release(void)
|
||||
bool DRW_gpu_context_release(void)
|
||||
{
|
||||
if (!BLI_thread_is_main()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GPU_context_active_get() != DST.gpu_context) {
|
||||
if (GPU_context_active_get() != DST.blender_gpu_context) {
|
||||
/* Context release is requested from the outside of the draw manager main draw loop, indicate
|
||||
* this to the `DRW_opengl_context_activate()` so that it restores drawable of the window. */
|
||||
* this to the `DRW_gpu_context_activate()` so that it restores drawable of the window.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
GPU_context_active_set(NULL);
|
||||
WM_opengl_context_release(DST.gl_context);
|
||||
WM_system_gpu_context_release(DST.system_gpu_context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DRW_opengl_context_activate(bool drw_state)
|
||||
void DRW_gpu_context_activate(bool drw_state)
|
||||
{
|
||||
if (!BLI_thread_is_main()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (drw_state) {
|
||||
WM_opengl_context_activate(DST.gl_context);
|
||||
GPU_context_active_set(DST.gpu_context);
|
||||
WM_system_gpu_context_activate(DST.system_gpu_context);
|
||||
GPU_context_active_set(DST.blender_gpu_context);
|
||||
}
|
||||
else {
|
||||
wm_window_reset_drawable();
|
||||
|
|
|
@ -666,13 +666,13 @@ typedef struct DRWManager {
|
|||
|
||||
/* ---------- Nothing after this point is cleared after use ----------- */
|
||||
|
||||
/* gl_context serves as the offset for clearing only
|
||||
/* system_gpu_context serves as the offset for clearing only
|
||||
* the top portion of the struct so DO NOT MOVE IT! */
|
||||
/** Unique ghost context used by the draw manager. */
|
||||
void *gl_context;
|
||||
GPUContext *gpu_context;
|
||||
void *system_gpu_context;
|
||||
GPUContext *blender_gpu_context;
|
||||
/** Mutex to lock the drw manager and avoid concurrent context usage. */
|
||||
TicketMutex *gl_context_mutex;
|
||||
TicketMutex *system_gpu_context_mutex;
|
||||
|
||||
GPUDrawList *draw_list;
|
||||
|
||||
|
|
|
@ -59,8 +59,8 @@ typedef struct DRWShaderCompiler {
|
|||
/** Optimization queue. */
|
||||
ListBase optimize_queue; /* GPUMaterial */
|
||||
|
||||
void *gl_context;
|
||||
GPUContext *gpu_context;
|
||||
void *system_gpu_context;
|
||||
GPUContext *blender_gpu_context;
|
||||
bool own_context;
|
||||
} DRWShaderCompiler;
|
||||
|
||||
|
@ -74,20 +74,20 @@ static void drw_deferred_shader_compilation_exec(
|
|||
{
|
||||
GPU_render_begin();
|
||||
DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data;
|
||||
void *gl_context = comp->gl_context;
|
||||
GPUContext *gpu_context = comp->gpu_context;
|
||||
void *system_gpu_context = comp->system_gpu_context;
|
||||
GPUContext *blender_gpu_context = comp->blender_gpu_context;
|
||||
|
||||
BLI_assert(gl_context != NULL);
|
||||
BLI_assert(gpu_context != NULL);
|
||||
BLI_assert(system_gpu_context != NULL);
|
||||
BLI_assert(blender_gpu_context != NULL);
|
||||
|
||||
const bool use_main_context_workaround = GPU_use_main_context_workaround();
|
||||
if (use_main_context_workaround) {
|
||||
BLI_assert(gl_context == DST.gl_context);
|
||||
BLI_assert(system_gpu_context == DST.system_gpu_context);
|
||||
GPU_context_main_lock();
|
||||
}
|
||||
|
||||
WM_opengl_context_activate(gl_context);
|
||||
GPU_context_active_set(gpu_context);
|
||||
WM_system_gpu_context_activate(system_gpu_context);
|
||||
GPU_context_active_set(blender_gpu_context);
|
||||
|
||||
while (true) {
|
||||
if (*stop != 0) {
|
||||
|
@ -145,7 +145,7 @@ static void drw_deferred_shader_compilation_exec(
|
|||
}
|
||||
|
||||
GPU_context_active_set(NULL);
|
||||
WM_opengl_context_release(gl_context);
|
||||
WM_system_gpu_context_release(system_gpu_context);
|
||||
if (use_main_context_workaround) {
|
||||
GPU_context_main_unlock();
|
||||
}
|
||||
|
@ -163,10 +163,10 @@ static void drw_deferred_shader_compilation_free(void *custom_data)
|
|||
|
||||
if (comp->own_context) {
|
||||
/* Only destroy if the job owns the context. */
|
||||
WM_opengl_context_activate(comp->gl_context);
|
||||
GPU_context_active_set(comp->gpu_context);
|
||||
GPU_context_discard(comp->gpu_context);
|
||||
WM_opengl_context_dispose(comp->gl_context);
|
||||
WM_system_gpu_context_activate(comp->system_gpu_context);
|
||||
GPU_context_active_set(comp->blender_gpu_context);
|
||||
GPU_context_discard(comp->blender_gpu_context);
|
||||
WM_system_gpu_context_dispose(comp->system_gpu_context);
|
||||
|
||||
wm_window_reset_drawable();
|
||||
}
|
||||
|
@ -204,9 +204,9 @@ static void drw_deferred_queue_append(GPUMaterial *mat, bool is_optimization_job
|
|||
BLI_movelisttolist(&comp->optimize_queue, &old_comp->optimize_queue);
|
||||
BLI_spin_unlock(&old_comp->list_lock);
|
||||
/* Do not recreate context, just pass ownership. */
|
||||
if (old_comp->gl_context) {
|
||||
comp->gl_context = old_comp->gl_context;
|
||||
comp->gpu_context = old_comp->gpu_context;
|
||||
if (old_comp->system_gpu_context) {
|
||||
comp->system_gpu_context = old_comp->system_gpu_context;
|
||||
comp->blender_gpu_context = old_comp->blender_gpu_context;
|
||||
old_comp->own_context = false;
|
||||
comp->own_context = job_own_context;
|
||||
}
|
||||
|
@ -226,18 +226,18 @@ static void drw_deferred_queue_append(GPUMaterial *mat, bool is_optimization_job
|
|||
}
|
||||
|
||||
/* Create only one context. */
|
||||
if (comp->gl_context == NULL) {
|
||||
if (comp->system_gpu_context == NULL) {
|
||||
if (use_main_context) {
|
||||
comp->gl_context = DST.gl_context;
|
||||
comp->gpu_context = DST.gpu_context;
|
||||
comp->system_gpu_context = DST.system_gpu_context;
|
||||
comp->blender_gpu_context = DST.blender_gpu_context;
|
||||
}
|
||||
else {
|
||||
comp->gl_context = WM_opengl_context_create();
|
||||
comp->gpu_context = GPU_context_create(NULL, comp->gl_context);
|
||||
comp->system_gpu_context = WM_system_gpu_context_create();
|
||||
comp->blender_gpu_context = GPU_context_create(NULL, comp->system_gpu_context);
|
||||
GPU_context_active_set(NULL);
|
||||
|
||||
WM_opengl_context_activate(DST.gl_context);
|
||||
GPU_context_active_set(DST.gpu_context);
|
||||
WM_system_gpu_context_activate(DST.system_gpu_context);
|
||||
GPU_context_active_set(DST.blender_gpu_context);
|
||||
}
|
||||
comp->own_context = job_own_context;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ uint *DRW_select_buffer_read(
|
|||
if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) {
|
||||
SELECTID_Context *select_ctx = DRW_select_engine_context_get();
|
||||
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
/* Update the drawing. */
|
||||
DRW_draw_select_id(depsgraph, region, v3d, rect);
|
||||
|
||||
|
@ -84,7 +84,7 @@ uint *DRW_select_buffer_read(
|
|||
}
|
||||
|
||||
GPU_framebuffer_restore();
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
}
|
||||
|
||||
if (r_buf_len) {
|
||||
|
|
|
@ -175,9 +175,9 @@ struct ObjectInfos {
|
|||
float4 infos;
|
||||
#else
|
||||
/** Uploaded as center + size. Converted to mul+bias to local coord. */
|
||||
float3 orco_add;
|
||||
packed_float3 orco_add;
|
||||
uint object_attrs_offset;
|
||||
float3 orco_mul;
|
||||
packed_float3 orco_mul;
|
||||
uint object_attrs_len;
|
||||
|
||||
float4 ob_color;
|
||||
|
|
|
@ -29,27 +29,27 @@ void main()
|
|||
vec3 diagonal = p01 + p02 + p03;
|
||||
vec3 center = p0 + diagonal * 0.5;
|
||||
float min_axis = min_v3(abs(diagonal));
|
||||
bounds_buf[resource_id].bounding_sphere.xyz = transform_point(model_mat, center);
|
||||
bounds.bounding_sphere.xyz = transform_point(model_mat, center);
|
||||
/* We have to apply scaling to the diagonal. */
|
||||
bounds_buf[resource_id].bounding_sphere.w = length(transform_direction(model_mat, diagonal)) *
|
||||
0.5;
|
||||
bounds_buf[resource_id]._inner_sphere_radius = min_axis;
|
||||
bounds_buf[resource_id].bounding_corners[0].xyz = transform_point(model_mat, p0);
|
||||
bounds_buf[resource_id].bounding_corners[1].xyz = transform_direction(model_mat, p01);
|
||||
bounds_buf[resource_id].bounding_corners[2].xyz = transform_direction(model_mat, p02);
|
||||
bounds_buf[resource_id].bounding_corners[3].xyz = transform_direction(model_mat, p03);
|
||||
bounds.bounding_sphere.w = length(transform_direction(model_mat, diagonal)) * 0.5;
|
||||
bounds._inner_sphere_radius = min_axis;
|
||||
bounds.bounding_corners[0].xyz = transform_point(model_mat, p0);
|
||||
bounds.bounding_corners[1].xyz = transform_direction(model_mat, p01);
|
||||
bounds.bounding_corners[2].xyz = transform_direction(model_mat, p02);
|
||||
bounds.bounding_corners[3].xyz = transform_direction(model_mat, p03);
|
||||
/* Always have correct handedness in the corners vectors. */
|
||||
if (flag_test(infos.flag, OBJECT_NEGATIVE_SCALE)) {
|
||||
bounds_buf[resource_id].bounding_corners[0].xyz +=
|
||||
bounds_buf[resource_id].bounding_corners[1].xyz;
|
||||
bounds_buf[resource_id].bounding_corners[1].xyz =
|
||||
-bounds_buf[resource_id].bounding_corners[1].xyz;
|
||||
bounds.bounding_corners[0].xyz += bounds.bounding_corners[1].xyz;
|
||||
bounds.bounding_corners[1].xyz = -bounds.bounding_corners[1].xyz;
|
||||
}
|
||||
|
||||
/* TODO: Bypass test for very large objects (see #67319). */
|
||||
if (bounds_buf[resource_id].bounding_sphere.w > 1e12) {
|
||||
bounds_buf[resource_id].bounding_sphere.w = -1.0;
|
||||
if (bounds.bounding_sphere.w > 1e12) {
|
||||
bounds.bounding_sphere.w = -1.0;
|
||||
}
|
||||
|
||||
/* Update bounds. */
|
||||
bounds_buf[resource_id] = bounds;
|
||||
}
|
||||
|
||||
vec3 loc = infos.orco_add; /* Box center. */
|
||||
|
|
|
@ -27,7 +27,7 @@ set(SRC
|
|||
anim_channels_edit.c
|
||||
anim_deps.c
|
||||
anim_draw.c
|
||||
anim_filter.c
|
||||
anim_filter.cc
|
||||
anim_ipo_utils.c
|
||||
anim_markers.c
|
||||
anim_motion_paths.c
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,9 +31,9 @@ ID_Type ED_asset_handle_get_id_type(const struct AssetHandle *asset);
|
|||
int ED_asset_handle_get_preview_icon_id(const struct AssetHandle *asset);
|
||||
void ED_asset_handle_get_full_library_path(
|
||||
const struct AssetHandle *asset,
|
||||
/* `1090` for #FILE_MAX_LIBEXTRA,
|
||||
/* `1024` for #FILE_MAX,
|
||||
* rely on warnings to let us know if this gets out of sync. */
|
||||
char r_full_lib_path[1090]);
|
||||
char r_full_lib_path[1024]);
|
||||
bool ED_asset_handle_get_use_relative_path(const struct AssetHandle *asset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -63,7 +63,7 @@ blender::StringRefNull ED_asset_handle_get_relative_path(const AssetHandle &asse
|
|||
}
|
||||
|
||||
void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
||||
char r_full_lib_path[FILE_MAX_LIBEXTRA])
|
||||
char r_full_lib_path[FILE_MAX])
|
||||
{
|
||||
*r_full_lib_path = '\0';
|
||||
|
||||
|
@ -73,7 +73,7 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
|||
return;
|
||||
}
|
||||
|
||||
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX_LIBEXTRA);
|
||||
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
|
||||
}
|
||||
|
||||
bool ED_asset_handle_get_use_relative_path(const AssetHandle *asset)
|
||||
|
|
|
@ -11751,6 +11751,7 @@ bool UI_textbutton_activate_rna(const bContext *C,
|
|||
if (but_text) {
|
||||
ARegion *region_ctx = CTX_wm_region(C);
|
||||
|
||||
/* Temporary context override for activating the button. */
|
||||
CTX_wm_region_set(const_cast<bContext *>(C), region);
|
||||
UI_but_active_only(C, region, block_text, but_text);
|
||||
CTX_wm_region_set(const_cast<bContext *>(C), region_ctx);
|
||||
|
|
|
@ -503,7 +503,7 @@ void paintface_select_loop(bContext *C, Object *ob, const int mval[2], const boo
|
|||
edge_to_poly_map,
|
||||
polys_to_select);
|
||||
|
||||
if (!traced_full_loop) {
|
||||
if (!traced_full_loop && polys_to_closest_edge.size() > 1) {
|
||||
/* Trace the other way. */
|
||||
follow_face_loop(polys_to_closest_edge[1],
|
||||
closest_edge_index,
|
||||
|
@ -519,8 +519,11 @@ void paintface_select_loop(bContext *C, Object *ob, const int mval[2], const boo
|
|||
|
||||
/* Toggling behavior. When one of the faces of the picked edge is already selected,
|
||||
* it deselects the loop instead. */
|
||||
const bool select_toggle = select && !(select_poly.span[polys_to_closest_edge[0]] ||
|
||||
select_poly.span[polys_to_closest_edge[1]]);
|
||||
bool any_adjacent_poly_selected = false;
|
||||
for (const int i : polys_to_closest_edge) {
|
||||
any_adjacent_poly_selected |= select_poly.span[i];
|
||||
}
|
||||
const bool select_toggle = select && !any_adjacent_poly_selected;
|
||||
select_poly.span.fill_indices(polys_to_select.as_span(), select_toggle);
|
||||
|
||||
select_poly.finish();
|
||||
|
|
|
@ -1088,7 +1088,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
RE_current_scene_update_cb(re, rj, current_scene_update);
|
||||
RE_stats_draw_cb(re, rj, image_renderinfo_cb);
|
||||
RE_progress_cb(re, rj, render_progress_update);
|
||||
RE_gl_context_create(re);
|
||||
RE_system_gpu_context_create(re);
|
||||
|
||||
rj->re = re;
|
||||
G.is_break = false;
|
||||
|
|
|
@ -302,7 +302,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
|
|||
uchar *gp_rect;
|
||||
uchar *render_rect = ibuf_result->byte_buffer.data;
|
||||
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
GPU_offscreen_bind(oglrender->ofs, true);
|
||||
|
||||
GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
@ -324,7 +324,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
|
|||
blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);
|
||||
}
|
||||
GPU_offscreen_unbind(oglrender->ofs, true);
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
|
||||
MEM_freeN(gp_rect);
|
||||
}
|
||||
|
@ -744,14 +744,14 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
|||
BKE_render_resolution(&scene->r, false, &sizex, &sizey);
|
||||
|
||||
/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
|
||||
DRW_opengl_context_enable(); /* Off-screen creation needs to be done in DRW context. */
|
||||
DRW_gpu_context_enable(); /* Off-screen creation needs to be done in DRW context. */
|
||||
ofs = GPU_offscreen_create(sizex,
|
||||
sizey,
|
||||
true,
|
||||
GPU_RGBA16F,
|
||||
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ,
|
||||
err_out);
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
|
||||
if (!ofs) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
|
||||
|
@ -925,9 +925,9 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
|
|||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
|
||||
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
GPU_offscreen_free(oglrender->ofs);
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
|
||||
if (oglrender->is_sequencer) {
|
||||
MEM_freeN(oglrender->seq_data.ibufs_arr);
|
||||
|
|
|
@ -243,7 +243,7 @@ static void compo_initjob(void *cjv)
|
|||
}
|
||||
|
||||
cj->re = RE_NewSceneRender(scene);
|
||||
RE_gl_context_create(cj->re);
|
||||
RE_system_gpu_context_create(cj->re);
|
||||
}
|
||||
|
||||
/* Called before redraw notifiers, it moves finished previews over. */
|
||||
|
@ -302,7 +302,7 @@ static void compo_startjob(void *cjv,
|
|||
}
|
||||
}
|
||||
|
||||
RE_gl_context_destroy(cj->re);
|
||||
RE_system_gpu_context_destroy(cj->re);
|
||||
|
||||
ntree->runtime->test_break = nullptr;
|
||||
ntree->runtime->stats_draw = nullptr;
|
||||
|
|
|
@ -1899,7 +1899,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
|
|||
}
|
||||
|
||||
const bool own_ofs = (ofs == nullptr);
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
|
||||
if (own_ofs) {
|
||||
/* bind */
|
||||
|
@ -1910,7 +1910,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
|
|||
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ,
|
||||
err_out);
|
||||
if (ofs == nullptr) {
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -2006,7 +2006,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
|
|||
GPU_offscreen_free(ofs);
|
||||
}
|
||||
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
|
||||
if (old_fb) {
|
||||
GPU_framebuffer_bind(old_fb);
|
||||
|
|
|
@ -666,7 +666,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
|
||||
|
||||
/* All of the queries need to be perform on the drawing context. */
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
|
||||
G.f |= G_FLAG_PICKSEL;
|
||||
|
||||
|
@ -746,7 +746,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
GPU_depth_test(GPU_DEPTH_NONE);
|
||||
}
|
||||
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
|
||||
UI_Theme_Restore(&theme_state);
|
||||
|
||||
|
|
|
@ -215,6 +215,7 @@ set(VULKAN_SRC
|
|||
vulkan/vk_drawlist.cc
|
||||
vulkan/vk_fence.cc
|
||||
vulkan/vk_framebuffer.cc
|
||||
vulkan/vk_image_view.cc
|
||||
vulkan/vk_immediate.cc
|
||||
vulkan/vk_index_buffer.cc
|
||||
vulkan/vk_memory.cc
|
||||
|
@ -250,6 +251,7 @@ set(VULKAN_SRC
|
|||
vulkan/vk_drawlist.hh
|
||||
vulkan/vk_fence.hh
|
||||
vulkan/vk_framebuffer.hh
|
||||
vulkan/vk_image_view.hh
|
||||
vulkan/vk_immediate.hh
|
||||
vulkan/vk_index_buffer.hh
|
||||
vulkan/vk_memory.hh
|
||||
|
|
|
@ -60,7 +60,7 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport,
|
|||
float dither);
|
||||
|
||||
/**
|
||||
* Should be called from DRW after DRW_opengl_context_enable.
|
||||
* Should be called from DRW after DRW_gpu_context_enable.
|
||||
*/
|
||||
void GPU_viewport_bind_from_offscreen(GPUViewport *viewport,
|
||||
struct GPUOffScreen *ofs,
|
||||
|
|
|
@ -43,21 +43,21 @@ void ShaderBuilder::init()
|
|||
{
|
||||
CLG_init();
|
||||
|
||||
GHOST_GLSettings glSettings = {0};
|
||||
GHOST_GPUSettings gpuSettings = {0};
|
||||
switch (GPU_backend_type_selection_get()) {
|
||||
case GPU_BACKEND_OPENGL:
|
||||
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
|
||||
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
|
||||
break;
|
||||
|
||||
#ifdef WITH_METAL_BACKEND
|
||||
case GPU_BACKEND_METAL:
|
||||
glSettings.context_type = GHOST_kDrawingContextTypeMetal;
|
||||
gpuSettings.context_type = GHOST_kDrawingContextTypeMetal;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
case GPU_BACKEND_VULKAN:
|
||||
glSettings.context_type = GHOST_kDrawingContextTypeVulkan;
|
||||
gpuSettings.context_type = GHOST_kDrawingContextTypeVulkan;
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -67,8 +67,8 @@ void ShaderBuilder::init()
|
|||
}
|
||||
|
||||
ghost_system_ = GHOST_CreateSystemBackground();
|
||||
ghost_context_ = GHOST_CreateOpenGLContext(ghost_system_, glSettings);
|
||||
GHOST_ActivateOpenGLContext(ghost_context_);
|
||||
ghost_context_ = GHOST_CreateGPUContext(ghost_system_, gpuSettings);
|
||||
GHOST_ActivateGPUContext(ghost_context_);
|
||||
|
||||
gpu_context_ = GPU_context_create(nullptr, ghost_context_);
|
||||
GPU_init();
|
||||
|
@ -80,7 +80,7 @@ void ShaderBuilder::exit()
|
|||
|
||||
GPU_context_discard(gpu_context_);
|
||||
|
||||
GHOST_DisposeOpenGLContext(ghost_system_, ghost_context_);
|
||||
GHOST_DisposeGPUContext(ghost_system_, ghost_context_);
|
||||
GHOST_DisposeSystem(ghost_system_);
|
||||
|
||||
CLG_exit();
|
||||
|
|
|
@ -194,7 +194,7 @@ void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect)
|
|||
rect_size[0] = BLI_rcti_size_x(rect) + 1;
|
||||
rect_size[1] = BLI_rcti_size_y(rect) + 1;
|
||||
|
||||
DRW_opengl_context_enable();
|
||||
DRW_gpu_context_enable();
|
||||
|
||||
if (!equals_v2v2_int(viewport->size, rect_size)) {
|
||||
copy_v2_v2_int(viewport->size, rect_size);
|
||||
|
@ -562,7 +562,7 @@ void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport,
|
|||
void GPU_viewport_unbind(GPUViewport *UNUSED(viewport))
|
||||
{
|
||||
GPU_framebuffer_restore();
|
||||
DRW_opengl_context_disable();
|
||||
DRW_gpu_context_disable();
|
||||
}
|
||||
|
||||
int GPU_viewport_active_view_get(GPUViewport *viewport)
|
||||
|
|
|
@ -51,7 +51,7 @@ GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list
|
|||
ghost_window_ = ghost_window;
|
||||
|
||||
if (ghost_window) {
|
||||
GLuint default_fbo = GHOST_GetDefaultOpenGLFramebuffer((GHOST_WindowHandle)ghost_window);
|
||||
GLuint default_fbo = GHOST_GetDefaultGPUFramebuffer((GHOST_WindowHandle)ghost_window);
|
||||
GHOST_RectangleHandle bounds = GHOST_GetClientBounds((GHOST_WindowHandle)ghost_window);
|
||||
int w = GHOST_GetWidthRectangle(bounds);
|
||||
int h = GHOST_GetHeightRectangle(bounds);
|
||||
|
|
|
@ -66,7 +66,7 @@ using uvec4 = uint4;
|
|||
|
||||
/* Compute decorators. */
|
||||
#define TG threadgroup
|
||||
#define barrier() threadgroup_barrier(mem_flags::mem_threadgroup)
|
||||
#define barrier() threadgroup_barrier(mem_flags::mem_threadgroup | mem_flags::mem_device | mem_flags::mem_texture)
|
||||
|
||||
#ifdef MTL_USE_WORKGROUP_SIZE
|
||||
/* Compute workgroup size. */
|
||||
|
|
|
@ -24,12 +24,12 @@ void GPUTest::SetUp()
|
|||
|
||||
CLG_init();
|
||||
GPU_backend_type_selection_set(gpu_backend_type);
|
||||
GHOST_GLSettings glSettings = {};
|
||||
glSettings.context_type = draw_context_type;
|
||||
glSettings.flags = GHOST_glDebugContext;
|
||||
GHOST_GPUSettings gpuSettings = {};
|
||||
gpuSettings.context_type = draw_context_type;
|
||||
gpuSettings.flags = GHOST_gpuDebugContext;
|
||||
ghost_system = GHOST_CreateSystem();
|
||||
ghost_context = GHOST_CreateOpenGLContext(ghost_system, glSettings);
|
||||
GHOST_ActivateOpenGLContext(ghost_context);
|
||||
ghost_context = GHOST_CreateGPUContext(ghost_system, gpuSettings);
|
||||
GHOST_ActivateGPUContext(ghost_context);
|
||||
context = GPU_context_create(nullptr, ghost_context);
|
||||
GPU_init();
|
||||
|
||||
|
@ -46,7 +46,7 @@ void GPUTest::TearDown()
|
|||
|
||||
GPU_exit();
|
||||
GPU_context_discard(context);
|
||||
GHOST_DisposeOpenGLContext(ghost_system, ghost_context);
|
||||
GHOST_DisposeGPUContext(ghost_system, ghost_context);
|
||||
GHOST_DisposeSystem(ghost_system);
|
||||
CLG_exit();
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ void VKDescriptorSetTracker::update(VKContext &context)
|
|||
binding.texture->layout_ensure(context, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
VkDescriptorImageInfo image_info = {};
|
||||
image_info.sampler = binding.vk_sampler;
|
||||
image_info.imageView = binding.texture->vk_image_view_handle();
|
||||
image_info.imageView = binding.texture->image_view_get().vk_handle();
|
||||
image_info.imageLayout = binding.texture->current_layout_get();
|
||||
image_infos.append(image_info);
|
||||
|
||||
|
|
|
@ -372,6 +372,8 @@ void VKFrameBuffer::render_pass_create()
|
|||
std::array<VkAttachmentDescription, GPU_FB_MAX_ATTACHMENT> attachment_descriptions;
|
||||
std::array<VkImageView, GPU_FB_MAX_ATTACHMENT> image_views;
|
||||
std::array<VkAttachmentReference, GPU_FB_MAX_ATTACHMENT> attachment_references;
|
||||
image_views_.clear();
|
||||
|
||||
bool has_depth_attachment = false;
|
||||
bool found_attachment = false;
|
||||
int depth_location = -1;
|
||||
|
@ -402,7 +404,8 @@ void VKFrameBuffer::render_pass_create()
|
|||
/* Ensure texture is allocated to ensure the image view. */
|
||||
VKTexture &texture = *static_cast<VKTexture *>(unwrap(attachment.tex));
|
||||
texture.ensure_allocated();
|
||||
image_views[attachment_location] = texture.vk_image_view_handle();
|
||||
image_views_.append(VKImageView(texture, attachment.mip, name_));
|
||||
image_views[attachment_location] = image_views_.last().vk_handle();
|
||||
|
||||
VkAttachmentDescription &attachment_description =
|
||||
attachment_descriptions[attachment_location];
|
||||
|
@ -411,10 +414,10 @@ void VKFrameBuffer::render_pass_create()
|
|||
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment_description.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
attachment_description.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment_description.initialLayout = texture.current_layout_get();
|
||||
attachment_description.finalLayout = texture.current_layout_get();
|
||||
|
||||
/* Create the attachment reference. */
|
||||
const bool is_depth_attachment = ELEM(
|
||||
|
@ -497,6 +500,7 @@ void VKFrameBuffer::render_pass_free()
|
|||
vkDestroyRenderPass(device.device_get(), vk_render_pass_, vk_allocation_callbacks);
|
||||
vkDestroyFramebuffer(device.device_get(), vk_framebuffer_, vk_allocation_callbacks);
|
||||
}
|
||||
image_views_.clear();
|
||||
vk_render_pass_ = VK_NULL_HANDLE;
|
||||
vk_framebuffer_ = VK_NULL_HANDLE;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "gpu_framebuffer_private.hh"
|
||||
|
||||
#include "vk_common.hh"
|
||||
#include "vk_image_view.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
|
@ -41,6 +42,8 @@ class VKFrameBuffer : public FrameBuffer {
|
|||
*/
|
||||
bool flip_viewport_ = false;
|
||||
|
||||
Vector<VKImageView, GPU_FB_MAX_ATTACHMENT> image_views_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a conventional framebuffer to attach texture to.
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#include "vk_image_view.hh"
|
||||
#include "vk_backend.hh"
|
||||
#include "vk_debug.hh"
|
||||
#include "vk_device.hh"
|
||||
#include "vk_memory.hh"
|
||||
#include "vk_texture.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
VKImageView::VKImageView(VKTexture &texture, int mip_level, StringRefNull name)
|
||||
: vk_image_view_(create_vk_image_view(texture, mip_level, name))
|
||||
{
|
||||
BLI_assert(vk_image_view_ != VK_NULL_HANDLE);
|
||||
}
|
||||
|
||||
VKImageView::VKImageView(VkImageView vk_image_view) : vk_image_view_(vk_image_view)
|
||||
{
|
||||
BLI_assert(vk_image_view_ != VK_NULL_HANDLE);
|
||||
}
|
||||
|
||||
VKImageView::VKImageView(VKImageView &&other)
|
||||
{
|
||||
vk_image_view_ = other.vk_image_view_;
|
||||
other.vk_image_view_ = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VKImageView::~VKImageView()
|
||||
{
|
||||
if (vk_image_view_ != VK_NULL_HANDLE) {
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vkDestroyImageView(device.device_get(), vk_image_view_, vk_allocation_callbacks);
|
||||
}
|
||||
}
|
||||
VkImageView VKImageView::create_vk_image_view(VKTexture &texture,
|
||||
int mip_level,
|
||||
StringRefNull name)
|
||||
{
|
||||
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
VkImageViewCreateInfo image_view_info = {};
|
||||
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
image_view_info.image = texture.vk_image_handle();
|
||||
image_view_info.viewType = to_vk_image_view_type(texture.type_get());
|
||||
image_view_info.format = to_vk_format(texture.format_get());
|
||||
image_view_info.components = to_vk_component_mapping(texture.format_get());
|
||||
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(texture.format_get());
|
||||
image_view_info.subresourceRange.baseMipLevel = mip_level;
|
||||
image_view_info.subresourceRange.levelCount = 1;
|
||||
image_view_info.subresourceRange.baseArrayLayer = 0;
|
||||
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
VkImageView image_view = VK_NULL_HANDLE;
|
||||
vkCreateImageView(device.device_get(), &image_view_info, vk_allocation_callbacks, &image_view);
|
||||
debug::object_label(image_view, name.c_str());
|
||||
return image_view;
|
||||
}
|
||||
|
||||
} // namespace blender::gpu
|
|
@ -0,0 +1,44 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vk_common.hh"
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
class VKTexture;
|
||||
|
||||
class VKImageView : NonCopyable {
|
||||
VkImageView vk_image_view_ = VK_NULL_HANDLE;
|
||||
|
||||
public:
|
||||
VKImageView(VKTexture &texture, int mip_level, StringRefNull name);
|
||||
|
||||
/**
|
||||
* Wrap the given vk_image_view handle. Note that the vk_image_view handle ownership is
|
||||
* transferred to VKImageView.
|
||||
*/
|
||||
VKImageView(VkImageView vk_image_view);
|
||||
|
||||
VKImageView(VKImageView &&other);
|
||||
~VKImageView();
|
||||
|
||||
VkImageView vk_handle() const
|
||||
{
|
||||
BLI_assert(vk_image_view_ != VK_NULL_HANDLE);
|
||||
return vk_image_view_;
|
||||
}
|
||||
|
||||
private:
|
||||
static VkImageView create_vk_image_view(VKTexture &texture, int mip_level, StringRefNull name);
|
||||
};
|
||||
|
||||
} // namespace blender::gpu
|
|
@ -25,11 +25,9 @@ namespace blender::gpu {
|
|||
|
||||
VKTexture::~VKTexture()
|
||||
{
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
if (is_allocated()) {
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vmaDestroyImage(device.mem_allocator_get(), vk_image_, allocation_);
|
||||
vkDestroyImageView(device.device_get(), vk_image_view_, vk_allocation_callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +81,9 @@ void VKTexture::generate_mipmap()
|
|||
*this,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
Span<VkImageBlit>(&image_blit, 1));
|
||||
/* TODO: Until we do actual command encoding we need to submit each transfer operation
|
||||
* individually. */
|
||||
command_buffer.submit();
|
||||
}
|
||||
/* Ensure that all mipmap levels are in `VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL`. All miplevels are
|
||||
* except the last one. */
|
||||
|
@ -148,9 +149,12 @@ void VKTexture::swizzle_set(const char /*swizzle_mask*/[4])
|
|||
NOT_YET_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void VKTexture::mip_range_set(int /*min*/, int /*max*/)
|
||||
void VKTexture::mip_range_set(int min, int max)
|
||||
{
|
||||
NOT_YET_IMPLEMENTED;
|
||||
mip_min_ = min;
|
||||
mip_max_ = max;
|
||||
|
||||
flags_ |= IMAGE_VIEW_DIRTY;
|
||||
}
|
||||
|
||||
void VKTexture::read_sub(int mip, eGPUDataFormat format, const int area[4], void *r_data)
|
||||
|
@ -430,20 +434,6 @@ bool VKTexture::allocate()
|
|||
/* Promote image to the correct layout. */
|
||||
layout_ensure(context, VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
VkImageViewCreateInfo image_view_info = {};
|
||||
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
image_view_info.image = vk_image_;
|
||||
image_view_info.viewType = to_vk_image_view_type(type_);
|
||||
image_view_info.format = to_vk_format(format_);
|
||||
image_view_info.components = to_vk_component_mapping(format_);
|
||||
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||
image_view_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
result = vkCreateImageView(
|
||||
device.device_get(), &image_view_info, vk_allocation_callbacks, &vk_image_view_);
|
||||
debug::object_label(vk_image_view_, name_);
|
||||
return result == VK_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -525,6 +515,48 @@ void VKTexture::layout_ensure(VKContext &context,
|
|||
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
context.command_buffer_get().pipeline_barrier(Span<VkImageMemoryBarrier>(&barrier, 1));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Image Views
|
||||
* \{ */
|
||||
|
||||
void VKTexture::image_view_ensure()
|
||||
{
|
||||
if (flags_ & IMAGE_VIEW_DIRTY) {
|
||||
image_view_update();
|
||||
flags_ &= ~IMAGE_VIEW_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
void VKTexture::image_view_update()
|
||||
{
|
||||
VK_ALLOCATION_CALLBACKS
|
||||
VkImageViewCreateInfo image_view_info = {};
|
||||
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
image_view_info.image = vk_image_;
|
||||
image_view_info.viewType = to_vk_image_view_type(type_);
|
||||
image_view_info.format = to_vk_format(format_);
|
||||
image_view_info.components = to_vk_component_mapping(format_);
|
||||
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||
IndexRange mip_range = mip_map_range();
|
||||
image_view_info.subresourceRange.baseMipLevel = mip_range.first();
|
||||
image_view_info.subresourceRange.levelCount = mip_range.size();
|
||||
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
VkImageView image_view = VK_NULL_HANDLE;
|
||||
vkCreateImageView(device.device_get(), &image_view_info, vk_allocation_callbacks, &image_view);
|
||||
debug::object_label(image_view, name_);
|
||||
image_view_.emplace(image_view);
|
||||
}
|
||||
|
||||
IndexRange VKTexture::mip_map_range() const
|
||||
{
|
||||
return IndexRange(mip_min_, mip_max_ - mip_min_ + 1);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "gpu_texture_private.hh"
|
||||
|
||||
#include "vk_context.hh"
|
||||
#include "vk_image_view.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
|
@ -17,15 +19,23 @@ class VKSampler;
|
|||
|
||||
class VKTexture : public Texture {
|
||||
VkImage vk_image_ = VK_NULL_HANDLE;
|
||||
VkImageView vk_image_view_ = VK_NULL_HANDLE;
|
||||
VmaAllocation allocation_ = VK_NULL_HANDLE;
|
||||
|
||||
/* Image view when used in a shader. */
|
||||
std::optional<VKImageView> image_view_;
|
||||
|
||||
/* Last image layout of the texture. Frame-buffer and barriers can alter/require the actual
|
||||
* layout to be changed. During this it requires to set the current layout in order to know which
|
||||
* conversion should happen. #current_layout_ keep track of the layout so the correct conversion
|
||||
* can be done. */
|
||||
VkImageLayout current_layout_ = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
enum eDirtyFlags {
|
||||
IMAGE_VIEW_DIRTY = (1 << 0),
|
||||
};
|
||||
|
||||
int flags_ = IMAGE_VIEW_DIRTY;
|
||||
|
||||
public:
|
||||
VKTexture(const char *name) : Texture(name) {}
|
||||
|
||||
|
@ -58,11 +68,6 @@ class VKTexture : public Texture {
|
|||
BLI_assert(vk_image_ != VK_NULL_HANDLE);
|
||||
return vk_image_;
|
||||
}
|
||||
VkImageView vk_image_view_handle() const
|
||||
{
|
||||
BLI_assert(is_allocated());
|
||||
return vk_image_view_;
|
||||
}
|
||||
|
||||
void ensure_allocated();
|
||||
|
||||
|
@ -123,6 +128,23 @@ class VKTexture : public Texture {
|
|||
VkImageLayout requested_layout);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Image Views
|
||||
* \{ */
|
||||
public:
|
||||
VKImageView &image_view_get()
|
||||
{
|
||||
image_view_ensure();
|
||||
return *image_view_;
|
||||
}
|
||||
|
||||
private:
|
||||
IndexRange mip_map_range() const;
|
||||
void image_view_ensure();
|
||||
void image_view_update();
|
||||
|
||||
/** \} */
|
||||
};
|
||||
|
||||
static inline VKTexture *unwrap(Texture *tex)
|
||||
|
|
|
@ -881,6 +881,12 @@ typedef struct NodeBilateralBlurData {
|
|||
char _pad[2];
|
||||
} NodeBilateralBlurData;
|
||||
|
||||
typedef struct NodeKuwaharaData {
|
||||
short size;
|
||||
short variation;
|
||||
int smoothing;
|
||||
} NodeKuwaharaData;
|
||||
|
||||
typedef struct NodeAntiAliasingData {
|
||||
float threshold;
|
||||
float contrast_limit;
|
||||
|
@ -2136,6 +2142,12 @@ typedef enum CMPNodeGlareType {
|
|||
CMP_NODE_GLARE_GHOST = 3,
|
||||
} CMPNodeGlareType;
|
||||
|
||||
/* Kuwahara Node. Stored in variation */
|
||||
typedef enum CMPNodeKuwahara {
|
||||
CMP_NODE_KUWAHARA_CLASSIC = 0,
|
||||
CMP_NODE_KUWAHARA_ANISOTROPIC = 1,
|
||||
} CMPNodeKuwahara;
|
||||
|
||||
/* Stabilize 2D node. Stored in custom1. */
|
||||
typedef enum CMPNodeStabilizeInterpolation {
|
||||
CMP_NODE_STABILIZE_INTERPOLATION_NEAREST = 0,
|
||||
|
|
|
@ -522,7 +522,7 @@ enum {
|
|||
/** #MovieTrackingTrack.pattern_match */
|
||||
typedef enum eTrackFrameMatch {
|
||||
TRACK_MATCH_KEYFRAME = 0,
|
||||
TRACK_MATCH_PREVIOS_FRAME = 1,
|
||||
TRACK_MATCH_PREVIOUS_FRAME = 1,
|
||||
} eTrackFrameMatch;
|
||||
|
||||
/** #MovieTrackingSettings.motion_flag */
|
||||
|
|
|
@ -9374,6 +9374,43 @@ static void def_cmp_denoise(StructRNA *srna)
|
|||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_cmp_kuwahara(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeKuwaharaData", "storage");
|
||||
|
||||
static const EnumPropertyItem variation_items[] = {
|
||||
{0, "CLASSIC", 0, "Classic", "Fast but less accurate variation"},
|
||||
{1, "ANISOTROPIC", 0, "Anisotropic", "Accurate but slower variation"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
prop = RNA_def_property(srna, "size", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "size");
|
||||
RNA_def_property_range(prop, 1.0, 100.0);
|
||||
RNA_def_property_ui_range(prop, 1, 100, 1, -1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Size", "Size of filter. Larger values give stronger stylized effect");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "variation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "variation");
|
||||
RNA_def_property_enum_items(prop, variation_items);
|
||||
RNA_def_property_ui_text(prop, "", "Variation of Kuwahara filter to use");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "smoothing", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "smoothing");
|
||||
RNA_def_property_range(prop, 0.0, 50.0);
|
||||
RNA_def_property_ui_range(prop, 0, 50, 1, -1);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Smoothing",
|
||||
"Smoothing degree before applying filter. Higher values remove details "
|
||||
"and give smoother edges");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_cmp_antialiasing(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
|
|
@ -2082,7 +2082,7 @@ static const EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSE
|
|||
}
|
||||
}
|
||||
|
||||
RNA_enum_item_end(&item, &totitem);
|
||||
RNA_enum_item_end(&item, &totitem_added);
|
||||
*r_free = true;
|
||||
|
||||
return item;
|
||||
|
|
|
@ -900,7 +900,7 @@ static const EnumPropertyItem tracker_motion_model[] = {
|
|||
|
||||
static const EnumPropertyItem pattern_match_items[] = {
|
||||
{TRACK_MATCH_KEYFRAME, "KEYFRAME", 0, "Keyframe", "Track pattern from keyframe to next frame"},
|
||||
{TRACK_MATCH_PREVIOS_FRAME,
|
||||
{TRACK_MATCH_PREVIOUS_FRAME,
|
||||
"PREV_FRAME",
|
||||
0,
|
||||
"Previous frame",
|
||||
|
|
|
@ -224,6 +224,7 @@ DefNode(CompositorNode, CMP_NODE_COMBINE_XYZ, 0, "COMBIN
|
|||
DefNode(CompositorNode, CMP_NODE_SEPARATE_XYZ, 0, "SEPARATE_XYZ", SeparateXYZ, "Separate XYZ", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_SEPARATE_COLOR, def_cmp_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_COMBINE_COLOR, def_cmp_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "" )
|
||||
DefNode(CompositorNode, CMP_NODE_KUWAHARA, def_cmp_kuwahara, "KUWAHARA", Kuwahara, "Kuwahara", "" )
|
||||
|
||||
DefNode(TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
|
||||
DefNode(TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
|
||||
|
|
|
@ -77,6 +77,7 @@ set(SRC
|
|||
nodes/node_composite_invert.cc
|
||||
nodes/node_composite_keying.cc
|
||||
nodes/node_composite_keyingscreen.cc
|
||||
nodes/node_composite_kuwahara.cc
|
||||
nodes/node_composite_lensdist.cc
|
||||
nodes/node_composite_levels.cc
|
||||
nodes/node_composite_luma_matte.cc
|
||||
|
|
|
@ -64,6 +64,7 @@ void register_composite_nodes()
|
|||
register_node_type_cmp_invert();
|
||||
register_node_type_cmp_keying();
|
||||
register_node_type_cmp_keyingscreen();
|
||||
register_node_type_cmp_kuwahara();
|
||||
register_node_type_cmp_lensdist();
|
||||
register_node_type_cmp_luma_matte();
|
||||
register_node_type_cmp_map_range();
|
||||
|
|
|
@ -60,6 +60,7 @@ void register_node_type_cmp_inpaint();
|
|||
void register_node_type_cmp_invert();
|
||||
void register_node_type_cmp_keying();
|
||||
void register_node_type_cmp_keyingscreen();
|
||||
void register_node_type_cmp_kuwahara();
|
||||
void register_node_type_cmp_lensdist();
|
||||
void register_node_type_cmp_luma_matte();
|
||||
void register_node_type_cmp_map_range();
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2023 Blender Foundation */
|
||||
|
||||
/** \file
|
||||
* \ingroup cmpnodes
|
||||
*/
|
||||
|
||||
#include "COM_node_operation.hh"
|
||||
|
||||
/* **************** Kuwahara ******************** */
|
||||
|
||||
namespace blender::nodes::node_composite_kuwahara_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodeKuwaharaData)
|
||||
|
||||
static void cmp_node_kuwahara_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>(N_("Image"))
|
||||
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
|
||||
.compositor_domain_priority(0);
|
||||
b.add_output<decl::Color>(N_("Image"));
|
||||
}
|
||||
|
||||
static void node_composit_init_kuwahara(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
NodeKuwaharaData *data = MEM_cnew<NodeKuwaharaData>(__func__);
|
||||
node->storage = data;
|
||||
|
||||
/* Set defaults. */
|
||||
data->size = 4;
|
||||
data->smoothing = 2;
|
||||
}
|
||||
|
||||
static void node_composit_buts_kuwahara(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiLayout *col;
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
|
||||
uiItemR(col, ptr, "variation", 0, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "size", 0, nullptr, ICON_NONE);
|
||||
|
||||
const int variation = RNA_enum_get(ptr, "variation");
|
||||
|
||||
if (variation == CMP_NODE_KUWAHARA_ANISOTROPIC) {
|
||||
uiItemR(col, ptr, "smoothing", 0, nullptr, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace blender::realtime_compositor;
|
||||
|
||||
class ConvertKuwaharaOperation : public NodeOperation {
|
||||
public:
|
||||
using NodeOperation::NodeOperation;
|
||||
|
||||
void execute() override
|
||||
{
|
||||
get_input("Image").pass_through(get_result("Image"));
|
||||
context().set_info_message("Viewport compositor setup not fully supported");
|
||||
}
|
||||
};
|
||||
|
||||
static NodeOperation *get_compositor_operation(Context &context, DNode node)
|
||||
{
|
||||
return new ConvertKuwaharaOperation(context, node);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_composite_kuwahara_cc
|
||||
|
||||
void register_node_type_cmp_kuwahara()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_composite_kuwahara_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
cmp_node_type_base(&ntype, CMP_NODE_KUWAHARA, "Kuwahara", NODE_CLASS_OP_FILTER);
|
||||
ntype.declare = file_ns::cmp_node_kuwahara_declare;
|
||||
ntype.draw_buttons = file_ns::node_composit_buts_kuwahara;
|
||||
ntype.initfunc = file_ns::node_composit_init_kuwahara;
|
||||
node_type_storage(
|
||||
&ntype, "NodeKuwaharaData", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
ntype.realtime_compositor_unsupported_message = N_(
|
||||
"Node not supported in the Viewport compositor");
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -9,15 +9,22 @@
|
|||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
|
||||
#include "COM_node_operation.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
#include "node_composite_util.hh"
|
||||
|
||||
namespace blender::nodes::node_composite_sunbeams_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodeSunBeams)
|
||||
|
||||
static void cmp_node_sunbeams_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>("Image").default_value({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
b.add_input<decl::Color>("Image")
|
||||
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
|
||||
.compositor_domain_priority(0);
|
||||
b.add_output<decl::Color>("Image");
|
||||
}
|
||||
|
||||
|
@ -49,8 +56,27 @@ class SunBeamsOperation : public NodeOperation {
|
|||
|
||||
void execute() override
|
||||
{
|
||||
get_input("Image").pass_through(get_result("Image"));
|
||||
context().set_info_message("Viewport compositor setup not fully supported");
|
||||
GPUShader *shader = shader_manager().get("compositor_sun_beams");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
GPU_shader_uniform_2fv(shader, "source", node_storage(bnode()).source);
|
||||
GPU_shader_uniform_1f(shader, "max_ray_length", node_storage(bnode()).ray_length);
|
||||
|
||||
const Result &input_image = get_input("Image");
|
||||
GPU_texture_filter_mode(input_image.texture(), true);
|
||||
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
|
||||
input_image.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const Domain domain = compute_domain();
|
||||
Result &output_image = get_result("Image");
|
||||
output_image.allocate_texture(domain);
|
||||
output_image.bind_as_image(shader, "output_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, domain.size);
|
||||
|
||||
GPU_shader_unbind();
|
||||
output_image.unbind_as_image();
|
||||
input_image.unbind_as_texture();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -74,8 +100,6 @@ void register_node_type_cmp_sunbeams()
|
|||
node_type_storage(
|
||||
&ntype, "NodeSunBeams", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
ntype.realtime_compositor_unsupported_message = N_(
|
||||
"Node not supported in the Viewport compositor");
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
|
|
@ -162,10 +162,10 @@ typedef struct RenderEngine {
|
|||
void *update_render_passes_data;
|
||||
|
||||
/* GPU context. */
|
||||
void *wm_gpu_context; /* WindowManager GPU context -> GHOSTContext. */
|
||||
ThreadMutex gpu_context_mutex;
|
||||
void *wm_blender_gpu_context; /* WindowManager GPU context -> GHOSTContext. */
|
||||
ThreadMutex blender_gpu_context_mutex;
|
||||
bool use_drw_render_context;
|
||||
struct GPUContext *gpu_context;
|
||||
struct GPUContext *blender_gpu_context;
|
||||
/* Whether to restore DRWState after RenderEngine display pass. */
|
||||
bool gpu_restore_context;
|
||||
} RenderEngine;
|
||||
|
@ -272,8 +272,6 @@ void RE_engines_init_experimental(void);
|
|||
void RE_engines_exit(void);
|
||||
void RE_engines_register(RenderEngineType *render_type);
|
||||
|
||||
bool RE_engine_is_opengl(RenderEngineType *render_type);
|
||||
|
||||
/**
|
||||
* Return true if the RenderEngineType has native support for direct loading of Alembic data. For
|
||||
* Cycles, this also checks that the experimental feature set is enabled.
|
||||
|
|
|
@ -426,10 +426,10 @@ void RE_current_scene_update_cb(struct Render *re,
|
|||
void *handle,
|
||||
void (*f)(void *handle, struct Scene *scene));
|
||||
|
||||
void RE_gl_context_create(Render *re);
|
||||
void RE_gl_context_destroy(Render *re);
|
||||
void *RE_gl_context_get(Render *re);
|
||||
void *RE_gpu_context_get(Render *re);
|
||||
void RE_system_gpu_context_create(Render *re);
|
||||
void RE_system_gpu_context_destroy(Render *re);
|
||||
void *RE_system_gpu_context_get(Render *re);
|
||||
void *RE_blender_gpu_context_get(Render *re);
|
||||
|
||||
/**
|
||||
* \param x: ranges from -1 to 1.
|
||||
|
|
|
@ -115,13 +115,6 @@ bool RE_engine_is_external(const Render *re)
|
|||
return (re->engine && re->engine->type && re->engine->type->render);
|
||||
}
|
||||
|
||||
bool RE_engine_is_opengl(RenderEngineType *render_type)
|
||||
{
|
||||
/* TODO: refine? Can we have OpenGL render engine without OpenGL render pipeline? */
|
||||
return (render_type->draw_engine != nullptr) &&
|
||||
DRW_engine_render_support(render_type->draw_engine);
|
||||
}
|
||||
|
||||
bool RE_engine_supports_alembic_procedural(const RenderEngineType *render_type, Scene *scene)
|
||||
{
|
||||
if ((render_type->flag & RE_USE_ALEMBIC_PROCEDURAL) == 0) {
|
||||
|
@ -143,7 +136,7 @@ RenderEngine *RE_engine_create(RenderEngineType *type)
|
|||
engine->type = type;
|
||||
|
||||
BLI_mutex_init(&engine->update_render_passes_mutex);
|
||||
BLI_mutex_init(&engine->gpu_context_mutex);
|
||||
BLI_mutex_init(&engine->blender_gpu_context_mutex);
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
@ -176,7 +169,7 @@ void RE_engine_free(RenderEngine *engine)
|
|||
|
||||
engine_depsgraph_free(engine);
|
||||
|
||||
BLI_mutex_end(&engine->gpu_context_mutex);
|
||||
BLI_mutex_end(&engine->blender_gpu_context_mutex);
|
||||
BLI_mutex_end(&engine->update_render_passes_mutex);
|
||||
|
||||
MEM_freeN(engine);
|
||||
|
@ -1271,7 +1264,7 @@ void RE_engine_tile_highlight_clear_all(RenderEngine *engine)
|
|||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name OpenGL context manipulation.
|
||||
/** \name GPU context manipulation.
|
||||
*
|
||||
* GPU context for engine to create and update GPU resources in its own thread,
|
||||
* without blocking the main thread. Used by Cycles' display driver to create
|
||||
|
@ -1282,7 +1275,7 @@ void RE_engine_tile_highlight_clear_all(RenderEngine *engine)
|
|||
bool RE_engine_gpu_context_create(RenderEngine *engine)
|
||||
{
|
||||
/* If the there already is a draw manager render context available, reuse it. */
|
||||
engine->use_drw_render_context = (engine->re && RE_gl_context_get(engine->re));
|
||||
engine->use_drw_render_context = (engine->re && RE_system_gpu_context_get(engine->re));
|
||||
if (engine->use_drw_render_context) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1291,49 +1284,49 @@ bool RE_engine_gpu_context_create(RenderEngine *engine)
|
|||
* the main thread here to safely create a context. */
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
|
||||
const bool drw_state = DRW_opengl_context_release();
|
||||
engine->wm_gpu_context = WM_opengl_context_create();
|
||||
const bool drw_state = DRW_gpu_context_release();
|
||||
engine->wm_blender_gpu_context = WM_system_gpu_context_create();
|
||||
|
||||
if (engine->wm_gpu_context) {
|
||||
/* Activate new OpenGL Context for GPUContext creation. */
|
||||
WM_opengl_context_activate(engine->wm_gpu_context);
|
||||
if (engine->wm_blender_gpu_context) {
|
||||
/* Activate new GPU Context for GPUContext creation. */
|
||||
WM_system_gpu_context_activate(engine->wm_blender_gpu_context);
|
||||
/* Requires GPUContext for usage of GPU Module for displaying results. */
|
||||
engine->gpu_context = GPU_context_create(nullptr, engine->wm_gpu_context);
|
||||
engine->blender_gpu_context = GPU_context_create(nullptr, engine->wm_blender_gpu_context);
|
||||
GPU_context_active_set(nullptr);
|
||||
/* Deactivate newly created OpenGL Context, as it is not needed until
|
||||
/* Deactivate newly created GPU Context, as it is not needed until
|
||||
* `RE_engine_gpu_context_enable` is called. */
|
||||
WM_opengl_context_release(engine->wm_gpu_context);
|
||||
WM_system_gpu_context_release(engine->wm_blender_gpu_context);
|
||||
}
|
||||
else {
|
||||
engine->gpu_context = nullptr;
|
||||
engine->blender_gpu_context = nullptr;
|
||||
}
|
||||
|
||||
DRW_opengl_context_activate(drw_state);
|
||||
DRW_gpu_context_activate(drw_state);
|
||||
|
||||
return engine->wm_gpu_context != nullptr;
|
||||
return engine->wm_blender_gpu_context != nullptr;
|
||||
}
|
||||
|
||||
void RE_engine_gpu_context_destroy(RenderEngine *engine)
|
||||
{
|
||||
if (!engine->wm_gpu_context) {
|
||||
if (!engine->wm_blender_gpu_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool drw_state = DRW_opengl_context_release();
|
||||
const bool drw_state = DRW_gpu_context_release();
|
||||
|
||||
WM_opengl_context_activate(engine->wm_gpu_context);
|
||||
if (engine->gpu_context) {
|
||||
WM_system_gpu_context_activate(engine->wm_blender_gpu_context);
|
||||
if (engine->blender_gpu_context) {
|
||||
GPUContext *restore_context = GPU_context_active_get();
|
||||
GPU_context_active_set(engine->gpu_context);
|
||||
GPU_context_discard(engine->gpu_context);
|
||||
if (restore_context != engine->gpu_context) {
|
||||
GPU_context_active_set(engine->blender_gpu_context);
|
||||
GPU_context_discard(engine->blender_gpu_context);
|
||||
if (restore_context != engine->blender_gpu_context) {
|
||||
GPU_context_active_set(restore_context);
|
||||
}
|
||||
engine->gpu_context = nullptr;
|
||||
engine->blender_gpu_context = nullptr;
|
||||
}
|
||||
WM_opengl_context_dispose(engine->wm_gpu_context);
|
||||
WM_system_gpu_context_dispose(engine->wm_blender_gpu_context);
|
||||
|
||||
DRW_opengl_context_activate(drw_state);
|
||||
DRW_gpu_context_activate(drw_state);
|
||||
}
|
||||
|
||||
bool RE_engine_gpu_context_enable(RenderEngine *engine)
|
||||
|
@ -1343,16 +1336,16 @@ bool RE_engine_gpu_context_enable(RenderEngine *engine)
|
|||
DRW_render_context_enable(engine->re);
|
||||
return true;
|
||||
}
|
||||
if (engine->wm_gpu_context) {
|
||||
BLI_mutex_lock(&engine->gpu_context_mutex);
|
||||
/* If a previous OpenGL/GPUContext was active (DST.gpu_context), we should later restore this
|
||||
* when disabling the RenderEngine context. */
|
||||
engine->gpu_restore_context = DRW_opengl_context_release();
|
||||
if (engine->wm_blender_gpu_context) {
|
||||
BLI_mutex_lock(&engine->blender_gpu_context_mutex);
|
||||
/* If a previous GPU/GPUContext was active (DST.blender_gpu_context), we should later
|
||||
* restore this when disabling the RenderEngine context. */
|
||||
engine->gpu_restore_context = DRW_gpu_context_release();
|
||||
|
||||
/* Activate RenderEngine OpenGL and GPU Context. */
|
||||
WM_opengl_context_activate(engine->wm_gpu_context);
|
||||
if (engine->gpu_context) {
|
||||
GPU_context_active_set(engine->gpu_context);
|
||||
/* Activate RenderEngine System and Blender GPU Context. */
|
||||
WM_system_gpu_context_activate(engine->wm_blender_gpu_context);
|
||||
if (engine->blender_gpu_context) {
|
||||
GPU_context_active_set(engine->blender_gpu_context);
|
||||
GPU_render_begin();
|
||||
}
|
||||
return true;
|
||||
|
@ -1366,15 +1359,15 @@ void RE_engine_gpu_context_disable(RenderEngine *engine)
|
|||
DRW_render_context_disable(engine->re);
|
||||
}
|
||||
else {
|
||||
if (engine->wm_gpu_context) {
|
||||
if (engine->gpu_context) {
|
||||
if (engine->wm_blender_gpu_context) {
|
||||
if (engine->blender_gpu_context) {
|
||||
GPU_render_end();
|
||||
GPU_context_active_set(nullptr);
|
||||
}
|
||||
WM_opengl_context_release(engine->wm_gpu_context);
|
||||
WM_system_gpu_context_release(engine->wm_blender_gpu_context);
|
||||
/* Restore DRW state context if previously active. */
|
||||
DRW_opengl_context_activate(engine->gpu_restore_context);
|
||||
BLI_mutex_unlock(&engine->gpu_context_mutex);
|
||||
DRW_gpu_context_activate(engine->gpu_restore_context);
|
||||
BLI_mutex_unlock(&engine->blender_gpu_context_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1385,8 +1378,8 @@ void RE_engine_gpu_context_lock(RenderEngine *engine)
|
|||
/* Locking already handled by the draw manager. */
|
||||
}
|
||||
else {
|
||||
if (engine->wm_gpu_context) {
|
||||
BLI_mutex_lock(&engine->gpu_context_mutex);
|
||||
if (engine->wm_blender_gpu_context) {
|
||||
BLI_mutex_lock(&engine->blender_gpu_context_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1397,8 +1390,8 @@ void RE_engine_gpu_context_unlock(RenderEngine *engine)
|
|||
/* Locking already handled by the draw manager. */
|
||||
}
|
||||
else {
|
||||
if (engine->wm_gpu_context) {
|
||||
BLI_mutex_unlock(&engine->gpu_context_mutex);
|
||||
if (engine->wm_blender_gpu_context) {
|
||||
BLI_mutex_unlock(&engine->blender_gpu_context_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -877,44 +877,44 @@ void RE_test_break_cb(Render *re, void *handle, bool (*f)(void *handle))
|
|||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name OpenGL Context
|
||||
/** \name GPU Context
|
||||
* \{ */
|
||||
|
||||
void RE_gl_context_create(Render *re)
|
||||
void RE_system_gpu_context_create(Render *re)
|
||||
{
|
||||
/* Needs to be created in the main OpenGL thread. */
|
||||
re->gl_context = WM_opengl_context_create();
|
||||
/* Needs to be created in the main thread. */
|
||||
re->system_gpu_context = WM_system_gpu_context_create();
|
||||
/* So we activate the window's one afterwards. */
|
||||
wm_window_reset_drawable();
|
||||
}
|
||||
|
||||
void RE_gl_context_destroy(Render *re)
|
||||
void RE_system_gpu_context_destroy(Render *re)
|
||||
{
|
||||
/* Needs to be called from the thread which used the OpenGL context for rendering. */
|
||||
if (re->gl_context) {
|
||||
if (re->gpu_context) {
|
||||
WM_opengl_context_activate(re->gl_context);
|
||||
GPU_context_active_set(static_cast<GPUContext *>(re->gpu_context));
|
||||
GPU_context_discard(static_cast<GPUContext *>(re->gpu_context));
|
||||
re->gpu_context = nullptr;
|
||||
/* Needs to be called from the thread which used the GPU context for rendering. */
|
||||
if (re->system_gpu_context) {
|
||||
if (re->blender_gpu_context) {
|
||||
WM_system_gpu_context_activate(re->system_gpu_context);
|
||||
GPU_context_active_set(static_cast<GPUContext *>(re->blender_gpu_context));
|
||||
GPU_context_discard(static_cast<GPUContext *>(re->blender_gpu_context));
|
||||
re->blender_gpu_context = nullptr;
|
||||
}
|
||||
|
||||
WM_opengl_context_dispose(re->gl_context);
|
||||
re->gl_context = nullptr;
|
||||
WM_system_gpu_context_dispose(re->system_gpu_context);
|
||||
re->system_gpu_context = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void *RE_gl_context_get(Render *re)
|
||||
void *RE_system_gpu_context_get(Render *re)
|
||||
{
|
||||
return re->gl_context;
|
||||
return re->system_gpu_context;
|
||||
}
|
||||
|
||||
void *RE_gpu_context_get(Render *re)
|
||||
void *RE_blender_gpu_context_get(Render *re)
|
||||
{
|
||||
if (re->gpu_context == nullptr) {
|
||||
re->gpu_context = GPU_context_create(nullptr, re->gl_context);
|
||||
if (re->blender_gpu_context == nullptr) {
|
||||
re->blender_gpu_context = GPU_context_create(nullptr, re->system_gpu_context);
|
||||
}
|
||||
return re->gpu_context;
|
||||
return re->blender_gpu_context;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1752,7 +1752,7 @@ static void render_pipeline_free(Render *re)
|
|||
re->pipeline_scene_eval = nullptr;
|
||||
}
|
||||
/* Destroy the opengl context in the correct thread. */
|
||||
RE_gl_context_destroy(re);
|
||||
RE_system_gpu_context_destroy(re);
|
||||
|
||||
/* In the case the engine did not mark tiles as finished (un-highlight, which could happen in the
|
||||
* case of cancelled render) ensure the storage is empty. */
|
||||
|
|
|
@ -124,8 +124,8 @@ struct Render {
|
|||
char viewname[MAX_NAME];
|
||||
|
||||
/* TODO: replace by a whole draw manager. */
|
||||
void *gl_context;
|
||||
void *gpu_context;
|
||||
void *system_gpu_context;
|
||||
void *blender_gpu_context;
|
||||
};
|
||||
|
||||
/* **************** defines ********************* */
|
||||
|
|
|
@ -144,7 +144,7 @@ void WM_init_splash_on_startup(struct bContext *C);
|
|||
*/
|
||||
void WM_init_splash(struct bContext *C);
|
||||
|
||||
void WM_init_opengl(void);
|
||||
void WM_init_gpu(void);
|
||||
|
||||
/**
|
||||
* Return an identifier for the underlying GHOST implementation.
|
||||
|
@ -313,10 +313,10 @@ void WM_window_ensure_active_view_layer(struct wmWindow *win) ATTR_NONNULL(1);
|
|||
|
||||
bool WM_window_is_temp_screen(const struct wmWindow *win) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
void *WM_opengl_context_create(void);
|
||||
void WM_opengl_context_dispose(void *context);
|
||||
void WM_opengl_context_activate(void *context);
|
||||
void WM_opengl_context_release(void *context);
|
||||
void *WM_system_gpu_context_create(void);
|
||||
void WM_system_gpu_context_dispose(void *context);
|
||||
void WM_system_gpu_context_activate(void *context);
|
||||
void WM_system_gpu_context_release(void *context);
|
||||
|
||||
/* #WM_window_open alignment */
|
||||
typedef enum eWindowAlignment {
|
||||
|
|
|
@ -1199,11 +1199,11 @@ static void wm_draw_surface(bContext *C, wmSurface *surface)
|
|||
wm_window_clear_drawable(CTX_wm_manager(C));
|
||||
wm_surface_make_drawable(surface);
|
||||
|
||||
GPU_context_begin_frame(surface->gpu_ctx);
|
||||
GPU_context_begin_frame(surface->blender_gpu_context);
|
||||
|
||||
surface->draw(C);
|
||||
|
||||
GPU_context_end_frame(surface->gpu_ctx);
|
||||
GPU_context_end_frame(surface->blender_gpu_context);
|
||||
|
||||
/* Avoid interference with window drawable */
|
||||
wm_surface_clear_drawable();
|
||||
|
|
|
@ -159,12 +159,12 @@ void WM_init_state_start_with_console_set(bool value)
|
|||
* so that it does not break anything that can run in headless mode (as in
|
||||
* without display server attached).
|
||||
*/
|
||||
static bool opengl_is_init = false;
|
||||
static bool gpu_is_init = false;
|
||||
|
||||
void WM_init_opengl(void)
|
||||
void WM_init_gpu(void)
|
||||
{
|
||||
/* Must be called only once. */
|
||||
BLI_assert(opengl_is_init == false);
|
||||
BLI_assert(gpu_is_init == false);
|
||||
|
||||
if (G.background) {
|
||||
/* Ghost is still not initialized elsewhere in background mode. */
|
||||
|
@ -176,13 +176,13 @@ void WM_init_opengl(void)
|
|||
}
|
||||
|
||||
/* Needs to be first to have an OpenGL context bound. */
|
||||
DRW_opengl_context_create();
|
||||
DRW_gpu_context_create();
|
||||
|
||||
GPU_init();
|
||||
|
||||
GPU_pass_cache_init();
|
||||
|
||||
opengl_is_init = true;
|
||||
gpu_is_init = true;
|
||||
}
|
||||
|
||||
static void sound_jack_sync_callback(Main *bmain, int mode, double time)
|
||||
|
@ -317,7 +317,7 @@ void WM_init(bContext *C, int argc, const char **argv)
|
|||
/* Sets 3D mouse dead-zone. */
|
||||
WM_ndof_deadzone_set(U.ndof_deadzone);
|
||||
#endif
|
||||
WM_init_opengl();
|
||||
WM_init_gpu();
|
||||
|
||||
if (!WM_platform_support_perform_checks()) {
|
||||
/* No attempt to avoid memory leaks here. */
|
||||
|
@ -603,7 +603,7 @@ void WM_exit_ex(bContext *C, const bool do_python, const bool do_user_exit_actio
|
|||
|
||||
BKE_subdiv_exit();
|
||||
|
||||
if (opengl_is_init) {
|
||||
if (gpu_is_init) {
|
||||
BKE_image_free_unused_gpu_textures();
|
||||
}
|
||||
|
||||
|
@ -617,7 +617,7 @@ void WM_exit_ex(bContext *C, const bool do_python, const bool do_user_exit_actio
|
|||
|
||||
/* Free the GPU subdivision data after the database to ensure that subdivision structs used by
|
||||
* the modifiers were garbage collected. */
|
||||
if (opengl_is_init) {
|
||||
if (gpu_is_init) {
|
||||
DRW_subdiv_free();
|
||||
}
|
||||
|
||||
|
@ -664,13 +664,13 @@ void WM_exit_ex(bContext *C, const bool do_python, const bool do_user_exit_actio
|
|||
|
||||
/* Delete GPU resources and context. The UI also uses GPU resources and so
|
||||
* is also deleted with the context active. */
|
||||
if (opengl_is_init) {
|
||||
DRW_opengl_context_enable_ex(false);
|
||||
if (gpu_is_init) {
|
||||
DRW_gpu_context_enable_ex(false);
|
||||
UI_exit();
|
||||
GPU_pass_cache_free();
|
||||
GPU_exit();
|
||||
DRW_opengl_context_disable_ex(false);
|
||||
DRW_opengl_context_destroy();
|
||||
DRW_gpu_context_disable_ex(false);
|
||||
DRW_gpu_context_destroy();
|
||||
}
|
||||
else {
|
||||
UI_exit();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue