/** * GAL Test Accessor Implementation * * Uses a member pointer technique to access private members without * the #define private public hack that breaks standard library headers. */ #include "gal_test_accessor.h" #include "kicad_stubs.h" #include #include #include // Template-based private member accessor trick // See: https://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html template struct result { typedef typename Tag::type type; static type ptr; }; template typename result::type result::ptr; template struct rob : result { struct filler { filler() { result::ptr = p; } }; static filler filler_obj; }; template typename rob::filler rob::filler_obj; // Tags for the private members we need to access struct OPENGL_GAL_compositor { typedef KIGFX::OPENGL_COMPOSITOR* KIGFX::OPENGL_GAL::*type; }; struct OPENGL_GAL_mainBuffer { typedef unsigned int KIGFX::OPENGL_GAL::*type; }; struct OPENGL_GAL_shader { typedef KIGFX::SHADER* KIGFX::OPENGL_GAL::*type; }; struct OPENGL_COMPOSITOR_mainFbo { typedef GLuint KIGFX::OPENGL_COMPOSITOR::*type; }; // Instantiate the accessors template struct rob; template struct rob; template struct rob; template struct rob; GLuint GetCompositorMainBufferTexture(KIGFX::OPENGL_GAL* gal) { // Get the compositor pointer using the member pointer accessor KIGFX::OPENGL_COMPOSITOR* compositor = gal->*result::ptr; unsigned int mainBuffer = gal->*result::ptr; if (compositor && mainBuffer > 0) { return compositor->GetBufferTexture(mainBuffer); } return 0; } void GetCompositorBufferSize(KIGFX::OPENGL_GAL* gal, int* width, int* height) { KIGFX::OPENGL_COMPOSITOR* compositor = gal->*result::ptr; if (compositor) { VECTOR2I size = compositor->GetScreenSize(); *width = size.x; *height = size.y; } else { *width = 0; *height = 0; } } GLuint GetCompositorMainFBO(KIGFX::OPENGL_GAL* gal) { KIGFX::OPENGL_COMPOSITOR* compositor = gal->*result::ptr; if (compositor) { return compositor->*result::ptr; } return 0; } unsigned int GetMainBufferHandle(KIGFX::OPENGL_GAL* gal) { return gal->*result::ptr; } bool ReadCompositorFBOPixels(KIGFX::OPENGL_GAL* gal, std::vector& pixels, int* width, int* height) { KIGFX::OPENGL_COMPOSITOR* compositor = gal->*result::ptr; unsigned int mainBuffer = gal->*result::ptr; if (!compositor || mainBuffer == 0) { return false; } GLuint mainFbo = compositor->*result::ptr; // Get size from compositor VECTOR2I size = compositor->GetScreenSize(); *width = size.x; *height = size.y; // Compute attachment point: GL_COLOR_ATTACHMENT0 + (mainBuffer - 1) GLenum attachmentPoint = GL_COLOR_ATTACHMENT0_EXT + (mainBuffer - 1); // Bind the FBO for reading glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mainFbo); glReadBuffer(attachmentPoint); // Read pixels pixels.resize((*width) * (*height) * 4); glReadPixels(0, 0, *width, *height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); // Unbind FBO glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); return true; } KIGFX::SHADER* GetGALShader(KIGFX::OPENGL_GAL* gal) { return gal->*result::ptr; } void DeactivateGALShader(KIGFX::OPENGL_GAL* gal) { KIGFX::SHADER* shader = gal->*result::ptr; if (shader) { shader->Deactivate(); } } void ActivateGALShader(KIGFX::OPENGL_GAL* gal) { KIGFX::SHADER* shader = gal->*result::ptr; if (shader) { shader->Use(); } }