Created
September 1, 2022 14:56
-
-
Save baku89/1bef0b4e07082d775f9808a5ef6c3fe0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /*******************************************************************/ | |
| /* */ | |
| /* ADOBE CONFIDENTIAL */ | |
| /* _ _ _ _ _ _ _ _ _ _ _ _ _ */ | |
| /* */ | |
| /* Copyright 2007-2015 Adobe Systems Incorporated */ | |
| /* All Rights Reserved. */ | |
| /* */ | |
| /* NOTICE: All information contained herein is, and remains the */ | |
| /* property of Adobe Systems Incorporated and its suppliers, if */ | |
| /* any. The intellectual and technical concepts contained */ | |
| /* herein are proprietary to Adobe Systems Incorporated and its */ | |
| /* suppliers and may be covered by U.S. and Foreign Patents, */ | |
| /* patents in process, and are protected by trade secret or */ | |
| /* copyright law. Dissemination of this information or */ | |
| /* reproduction of this material is strictly forbidden unless */ | |
| /* prior written permission is obtained from Adobe Systems */ | |
| /* Incorporated. */ | |
| /* */ | |
| /*******************************************************************/ | |
| /* GLator.cpp | |
| This is a sample OpenGL plugin. The framework is done for you. | |
| Use it to create more funky effects. | |
| Revision History | |
| Version Change Engineer Date | |
| ======= ====== ======== ====== | |
| 1.0 Win and Mac versions use the same base files. anindyar 7/4/2007 | |
| 1.1 Add OpenGL context switching to play nicely with | |
| AE's own OpenGL usage (thanks Brendan Bolles!) zal 8/13/2012 | |
| 2.0 Completely re-written for OGL 3.3 and threads aparente 9/30/2015 | |
| 2.1 Added new entry point zal 9/15/2017 | |
| */ | |
| #include "GLator.h" | |
| #include "GL_base.h" | |
| #include "Smart_Utils.h" | |
| #include "AEFX_SuiteHelper.h" | |
| #include <thread> | |
| #include <atomic> | |
| #include <map> | |
| #include <mutex> | |
| #include "vmath.hpp" | |
| #include <assert.h> | |
| using namespace AESDK_OpenGL; | |
| using namespace gl33core; | |
| #include "glbinding/gl33ext/gl.h" | |
| #include <glbinding/gl/extension.h> | |
| /* AESDK_OpenGL effect specific variables */ | |
| namespace { | |
| THREAD_LOCAL int t_thread = -1; | |
| std::atomic_int S_cnt; | |
| std::map<int, std::shared_ptr<AESDK_OpenGL::AESDK_OpenGL_EffectRenderData> > S_render_contexts; | |
| std::recursive_mutex S_mutex; | |
| AESDK_OpenGL::AESDK_OpenGL_EffectCommonDataPtr S_GLator_EffectCommonData; //global context | |
| std::string S_ResourcePath; | |
| // - OpenGL resources are restricted per thread, mimicking the OGL driver | |
| // - The filter will eliminate all TLS (Thread Local Storage) at PF_Cmd_GLOBAL_SETDOWN | |
| AESDK_OpenGL::AESDK_OpenGL_EffectRenderDataPtr GetCurrentRenderContext() | |
| { | |
| S_mutex.lock(); | |
| AESDK_OpenGL::AESDK_OpenGL_EffectRenderDataPtr result; | |
| if (t_thread == -1) { | |
| t_thread = S_cnt++; | |
| result.reset(new AESDK_OpenGL::AESDK_OpenGL_EffectRenderData()); | |
| S_render_contexts[t_thread] = result; | |
| } | |
| else { | |
| result = S_render_contexts[t_thread]; | |
| } | |
| S_mutex.unlock(); | |
| return result; | |
| } | |
| #ifdef AE_OS_WIN | |
| std::string get_string_from_wcs(const wchar_t* pcs) | |
| { | |
| int res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, NULL, 0, NULL, NULL); | |
| std::auto_ptr<char> shared_pbuf(new char[res]); | |
| char *pbuf = shared_pbuf.get(); | |
| res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, pbuf, res, NULL, NULL); | |
| return std::string(pbuf); | |
| } | |
| #endif | |
| void RenderQuad(GLuint vbo) | |
| { | |
| glEnableVertexAttribArray(PositionSlot); | |
| glEnableVertexAttribArray(UVSlot); | |
| glBindBuffer(GL_ARRAY_BUFFER, vbo); | |
| glVertexAttribPointer(PositionSlot, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 0); | |
| glVertexAttribPointer(UVSlot, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); | |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
| glDisableVertexAttribArray(PositionSlot); | |
| glDisableVertexAttribArray(UVSlot); | |
| glBindBuffer(GL_ARRAY_BUFFER, 0); | |
| } | |
| std::string GetResourcesPath(PF_InData *in_data) | |
| { | |
| //initialize and compile the shader objects | |
| A_UTF16Char pluginFolderPath[AEFX_MAX_PATH]; | |
| PF_GET_PLATFORM_DATA(PF_PlatData_EXE_FILE_PATH_W, &pluginFolderPath); | |
| #ifdef AE_OS_WIN | |
| std::string resourcePath = get_string_from_wcs((wchar_t*)pluginFolderPath); | |
| std::string::size_type pos; | |
| //delete the plugin name | |
| pos = resourcePath.rfind("\\", resourcePath.length()); | |
| resourcePath = resourcePath.substr(0, pos) + "\\"; | |
| #endif | |
| #ifdef AE_OS_MAC | |
| NSUInteger length = 0; | |
| A_UTF16Char* tmp = pluginFolderPath; | |
| while (*tmp++ != 0) { | |
| ++length; | |
| } | |
| NSString* newStr = [[NSString alloc] initWithCharacters:pluginFolderPath length : length]; | |
| std::string resourcePath([newStr UTF8String]); | |
| resourcePath += "/Contents/Resources/"; | |
| #endif | |
| return resourcePath; | |
| } | |
| struct CopyPixelFloat_t { | |
| PF_PixelFloat *floatBufferP; | |
| PF_EffectWorld *input_worldP; | |
| }; | |
| PF_Err | |
| CopyPixelFloatIn( | |
| void *refcon, | |
| A_long x, | |
| A_long y, | |
| PF_PixelFloat *inP, | |
| PF_PixelFloat *) | |
| { | |
| CopyPixelFloat_t *thiS = reinterpret_cast<CopyPixelFloat_t*>(refcon); | |
| PF_PixelFloat *outP = thiS->floatBufferP + y * thiS->input_worldP->width + x; | |
| outP->red = inP->red; | |
| outP->green = inP->green; | |
| outP->blue = inP->blue; | |
| outP->alpha = inP->alpha; | |
| return PF_Err_NONE; | |
| } | |
| PF_Err | |
| CopyPixelFloatOut( | |
| void *refcon, | |
| A_long x, | |
| A_long y, | |
| PF_PixelFloat *, | |
| PF_PixelFloat *outP) | |
| { | |
| CopyPixelFloat_t *thiS = reinterpret_cast<CopyPixelFloat_t*>(refcon); | |
| const PF_PixelFloat *inP = thiS->floatBufferP + y * thiS->input_worldP->width + x; | |
| outP->red = inP->red; | |
| outP->green = inP->green; | |
| outP->blue = inP->blue; | |
| outP->alpha = inP->alpha; | |
| return PF_Err_NONE; | |
| } | |
| gl::GLuint UploadTexture(AEGP_SuiteHandler& suites, // >> | |
| PF_PixelFormat format, // >> | |
| PF_EffectWorld *input_worldP, // >> | |
| PF_EffectWorld *output_worldP, // >> | |
| PF_InData *in_data, // >> | |
| size_t& pixSizeOut, // << | |
| gl::GLenum& glFmtOut, // << | |
| float& multiplier16bitOut) // << | |
| { | |
| // - upload to texture memory | |
| // - we will convert on-the-fly from ARGB to RGBA, and also to pre-multiplied alpha, | |
| // using a fragment shader | |
| #ifdef _DEBUG | |
| GLint nUnpackAlignment; | |
| ::glGetIntegerv(GL_UNPACK_ALIGNMENT, &nUnpackAlignment); | |
| assert(nUnpackAlignment == 4); | |
| #endif | |
| gl::GLuint inputFrameTexture; | |
| glGenTextures(1, &inputFrameTexture); | |
| glBindTexture(GL_TEXTURE_2D, inputFrameTexture); | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)GL_LINEAR); | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)GL_LINEAR); | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLint)GL_CLAMP_TO_EDGE); | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLint)GL_CLAMP_TO_EDGE); | |
| glTexImage2D(GL_TEXTURE_2D, 0, (GLint)GL_RGBA32F, input_worldP->width, input_worldP->height, 0, GL_RGBA, GL_FLOAT, nullptr); | |
| multiplier16bitOut = 1.0f; | |
| switch (format) | |
| { | |
| case PF_PixelFormat_ARGB128: | |
| { | |
| glFmtOut = GL_FLOAT; | |
| pixSizeOut = sizeof(PF_PixelFloat); | |
| std::auto_ptr<PF_PixelFloat> bufferFloat(new PF_PixelFloat[input_worldP->width * input_worldP->height]); | |
| CopyPixelFloat_t refcon = { bufferFloat.get(), input_worldP }; | |
| CHECK(suites.IterateFloatSuite2()->iterate(in_data, | |
| 0, | |
| input_worldP->height, | |
| input_worldP, | |
| nullptr, | |
| reinterpret_cast<void*>(&refcon), | |
| CopyPixelFloatIn, | |
| output_worldP)); | |
| glPixelStorei(GL_UNPACK_ROW_LENGTH, input_worldP->width); | |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, input_worldP->width, input_worldP->height, GL_RGBA, GL_FLOAT, bufferFloat.get()); | |
| break; | |
| } | |
| case PF_PixelFormat_ARGB64: | |
| { | |
| glFmtOut = GL_UNSIGNED_SHORT; | |
| pixSizeOut = sizeof(PF_Pixel16); | |
| multiplier16bitOut = 65535.0f / 32768.0f; | |
| glPixelStorei(GL_UNPACK_ROW_LENGTH, input_worldP->rowbytes / sizeof(PF_Pixel16)); | |
| PF_Pixel16 *pixelDataStart = NULL; | |
| PF_GET_PIXEL_DATA16(input_worldP, NULL, &pixelDataStart); | |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, input_worldP->width, input_worldP->height, GL_RGBA, GL_UNSIGNED_SHORT, pixelDataStart); | |
| break; | |
| } | |
| case PF_PixelFormat_ARGB32: | |
| { | |
| glFmtOut = GL_UNSIGNED_BYTE; | |
| pixSizeOut = sizeof(PF_Pixel8); | |
| glPixelStorei(GL_UNPACK_ROW_LENGTH, input_worldP->rowbytes / sizeof(PF_Pixel8)); | |
| PF_Pixel8 *pixelDataStart = NULL; | |
| PF_GET_PIXEL_DATA8(input_worldP, NULL, &pixelDataStart); | |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, input_worldP->width, input_worldP->height, GL_RGBA, GL_UNSIGNED_BYTE, pixelDataStart); | |
| break; | |
| } | |
| default: | |
| CHECK(PF_Err_BAD_CALLBACK_PARAM); | |
| break; | |
| } | |
| glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | |
| //unbind all textures | |
| glBindTexture(GL_TEXTURE_2D, 0); | |
| return inputFrameTexture; | |
| } | |
| void ReportIfErrorFramebuffer(PF_InData *in_data, PF_OutData *out_data) | |
| { | |
| // Check for errors... | |
| std::string error_msg; | |
| if ((error_msg = CheckFramebufferStatus()) != std::string("OK")) | |
| { | |
| out_data->out_flags |= PF_OutFlag_DISPLAY_ERROR_MESSAGE; | |
| PF_SPRINTF(out_data->return_msg, error_msg.c_str()); | |
| CHECK(PF_Err_OUT_OF_MEMORY); | |
| } | |
| } | |
| void SwizzleGL(const AESDK_OpenGL::AESDK_OpenGL_EffectRenderDataPtr& renderContext, | |
| A_long widthL, A_long heightL, | |
| gl::GLuint inputFrameTexture, | |
| float multiplier16bit) | |
| { | |
| glBindTexture(GL_TEXTURE_2D, inputFrameTexture); | |
| glUseProgram(renderContext->mProgramObj2Su); | |
| // view matrix, mimic windows coordinates | |
| vmath::Matrix4 ModelviewProjection = vmath::Matrix4::translation(vmath::Vector3(-1.0f, -1.0f, 0.0f)) * | |
| vmath::Matrix4::scale(vmath::Vector3(2.0 / float(widthL), 2.0 / float(heightL), 1.0f)); | |
| GLint location = glGetUniformLocation(renderContext->mProgramObj2Su, "ModelviewProjection"); | |
| glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)&ModelviewProjection); | |
| location = glGetUniformLocation(renderContext->mProgramObj2Su, "multiplier16bit"); | |
| glUniform1f(location, multiplier16bit); | |
| AESDK_OpenGL_BindTextureToTarget(renderContext->mProgramObj2Su, inputFrameTexture, std::string("videoTexture")); | |
| // render | |
| glBindVertexArray(renderContext->vao); | |
| RenderQuad(renderContext->quad); | |
| glBindVertexArray(0); | |
| glUseProgram(0); | |
| glFlush(); | |
| } | |
| void RenderGL(const AESDK_OpenGL::AESDK_OpenGL_EffectRenderDataPtr& renderContext, | |
| A_long widthL, A_long heightL, | |
| gl::GLuint inputFrameTexture, | |
| PF_FpLong sliderVal, | |
| float multiplier16bit) | |
| { | |
| // - make sure we blend correctly inside the framebuffer | |
| // - even though we just cleared it, another effect may want to first | |
| // draw some kind of background to blend with | |
| glEnable(GL_BLEND); | |
| glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); | |
| glBlendEquation(GL_FUNC_ADD); | |
| // view matrix, mimic windows coordinates | |
| vmath::Matrix4 ModelviewProjection = vmath::Matrix4::translation(vmath::Vector3(-1.0f, -1.0f, 0.0f)) * | |
| vmath::Matrix4::scale(vmath::Vector3(2.0 / float(widthL), 2.0 / float(heightL), 1.0f)); | |
| glBindTexture(GL_TEXTURE_2D, inputFrameTexture); | |
| glUseProgram(renderContext->mProgramObjSu); | |
| // program uniforms | |
| GLint location = glGetUniformLocation(renderContext->mProgramObjSu, "ModelviewProjection"); | |
| glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)&ModelviewProjection); | |
| location = glGetUniformLocation(renderContext->mProgramObjSu, "sliderVal"); | |
| glUniform1f(location, sliderVal); | |
| location = glGetUniformLocation(renderContext->mProgramObjSu, "multiplier16bit"); | |
| glUniform1f(location, multiplier16bit); | |
| // Identify the texture to use and bind it to texture unit 0 | |
| AESDK_OpenGL_BindTextureToTarget(renderContext->mProgramObjSu, inputFrameTexture, std::string("videoTexture")); | |
| // render | |
| glBindVertexArray(renderContext->vao); | |
| RenderQuad(renderContext->quad); | |
| glBindVertexArray(0); | |
| glUseProgram(0); | |
| glDisable(GL_BLEND); | |
| } | |
| void DownloadTexture(const AESDK_OpenGL::AESDK_OpenGL_EffectRenderDataPtr& renderContext, | |
| AEGP_SuiteHandler& suites, // >> | |
| PF_EffectWorld *input_worldP, // >> | |
| PF_EffectWorld *output_worldP, // >> | |
| PF_InData *in_data, // >> | |
| PF_PixelFormat format, // >> | |
| size_t pixSize, // >> | |
| gl::GLenum glFmt // >> | |
| ) | |
| { | |
| //download from texture memory onto the same surface | |
| PF_Handle bufferH = NULL; | |
| bufferH = suites.HandleSuite1()->host_new_handle(((renderContext->mRenderBufferWidthSu * renderContext->mRenderBufferHeightSu)* pixSize)); | |
| if (!bufferH) { | |
| CHECK(PF_Err_OUT_OF_MEMORY); | |
| } | |
| void *bufferP = suites.HandleSuite1()->host_lock_handle(bufferH); | |
| glReadBuffer(GL_COLOR_ATTACHMENT0); | |
| glReadPixels(0, 0, renderContext->mRenderBufferWidthSu, renderContext->mRenderBufferHeightSu, GL_RGBA, glFmt, bufferP); | |
| switch (format) | |
| { | |
| case PF_PixelFormat_ARGB128: | |
| { | |
| PF_PixelFloat* bufferFloatP = reinterpret_cast<PF_PixelFloat*>(bufferP); | |
| CopyPixelFloat_t refcon = { bufferFloatP, input_worldP }; | |
| CHECK(suites.IterateFloatSuite2()->iterate(in_data, | |
| 0, | |
| input_worldP->height, | |
| input_worldP, | |
| nullptr, | |
| reinterpret_cast<void*>(&refcon), | |
| CopyPixelFloatOut, | |
| output_worldP)); | |
| break; | |
| } | |
| case PF_PixelFormat_ARGB64: | |
| { | |
| PF_Pixel16* buffer16P = reinterpret_cast<PF_Pixel16*>(bufferP); | |
| //copy to output_worldP | |
| for (int y = 0; y < output_worldP->height; ++y) | |
| { | |
| PF_Pixel16 *pixelDataStart = NULL; | |
| PF_GET_PIXEL_DATA16(output_worldP, NULL, &pixelDataStart); | |
| ::memcpy(pixelDataStart + (y * output_worldP->rowbytes / sizeof(PF_Pixel16)), | |
| buffer16P + (y * renderContext->mRenderBufferWidthSu), | |
| output_worldP->width * sizeof(PF_Pixel16)); | |
| } | |
| break; | |
| } | |
| case PF_PixelFormat_ARGB32: | |
| { | |
| PF_Pixel8 *buffer8P = reinterpret_cast<PF_Pixel8*>(bufferP); | |
| //copy to output_worldP | |
| for (int y = 0; y < output_worldP->height; ++y) | |
| { | |
| PF_Pixel8 *pixelDataStart = NULL; | |
| PF_GET_PIXEL_DATA8(output_worldP, NULL, &pixelDataStart); | |
| ::memcpy(pixelDataStart + (y * output_worldP->rowbytes / sizeof(PF_Pixel8)), | |
| buffer8P + (y * renderContext->mRenderBufferWidthSu), | |
| output_worldP->width * sizeof(PF_Pixel8)); | |
| } | |
| break; | |
| } | |
| default: | |
| CHECK(PF_Err_BAD_CALLBACK_PARAM); | |
| break; | |
| } | |
| //clean the data after being copied | |
| suites.HandleSuite1()->host_unlock_handle(bufferH); | |
| suites.HandleSuite1()->host_dispose_handle(bufferH); | |
| } | |
| } // anonymous namespace | |
| static PF_Err | |
| About ( | |
| PF_InData *in_data, | |
| PF_OutData *out_data, | |
| PF_ParamDef *params[], | |
| PF_LayerDef *output ) | |
| { | |
| AEGP_SuiteHandler suites(in_data->pica_basicP); | |
| suites.ANSICallbacksSuite1()->sprintf( out_data->return_msg, | |
| "%s v%d.%d\r%s", | |
| STR(StrID_Name), | |
| MAJOR_VERSION, | |
| MINOR_VERSION, | |
| STR(StrID_Description)); | |
| return PF_Err_NONE; | |
| } | |
| static PF_Err | |
| GlobalSetup ( | |
| PF_InData *in_data, | |
| PF_OutData *out_data, | |
| PF_ParamDef *params[], | |
| PF_LayerDef *output ) | |
| { | |
| out_data->my_version = PF_VERSION( MAJOR_VERSION, | |
| MINOR_VERSION, | |
| BUG_VERSION, | |
| STAGE_VERSION, | |
| BUILD_VERSION); | |
| out_data->out_flags = PF_OutFlag_DEEP_COLOR_AWARE; | |
| out_data->out_flags2 = PF_OutFlag2_FLOAT_COLOR_AWARE | | |
| PF_OutFlag2_SUPPORTS_SMART_RENDER; | |
| PF_Err err = PF_Err_NONE; | |
| try | |
| { | |
| // always restore back AE's own OGL context | |
| SaveRestoreOGLContext oSavedContext; | |
| AEGP_SuiteHandler suites(in_data->pica_basicP); | |
| //Now comes the OpenGL part - OS specific loading to start with | |
| S_GLator_EffectCommonData.reset(new AESDK_OpenGL::AESDK_OpenGL_EffectCommonData()); | |
| AESDK_OpenGL_Startup(*S_GLator_EffectCommonData.get()); | |
| S_ResourcePath = GetResourcesPath(in_data); | |
| } | |
| catch(PF_Err& thrown_err) | |
| { | |
| err = thrown_err; | |
| } | |
| catch (...) | |
| { | |
| err = PF_Err_OUT_OF_MEMORY; | |
| } | |
| return err; | |
| } | |
| static PF_Err | |
| ParamsSetup ( | |
| PF_InData *in_data, | |
| PF_OutData *out_data, | |
| PF_ParamDef *params[], | |
| PF_LayerDef *output ) | |
| { | |
| PF_Err err = PF_Err_NONE; | |
| PF_ParamDef def; | |
| AEFX_CLR_STRUCT(def); | |
| PF_ADD_SLIDER( STR(StrID_Name), | |
| GLATOR_SLIDER_MIN, | |
| GLATOR_SLIDER_MAX, | |
| GLATOR_SLIDER_MIN, | |
| GLATOR_SLIDER_MAX, | |
| GLATOR_SLIDER_DFLT, | |
| SLIDER_DISK_ID); | |
| out_data->num_params = GLATOR_NUM_PARAMS; | |
| return err; | |
| } | |
| static PF_Err | |
| GlobalSetdown ( | |
| PF_InData *in_data, | |
| PF_OutData *out_data, | |
| PF_ParamDef *params[], | |
| PF_LayerDef *output ) | |
| { | |
| PF_Err err = PF_Err_NONE; | |
| try | |
| { | |
| // always restore back AE's own OGL context | |
| SaveRestoreOGLContext oSavedContext; | |
| S_mutex.lock(); | |
| S_render_contexts.clear(); | |
| S_mutex.unlock(); | |
| //OS specific unloading | |
| AESDK_OpenGL_Shutdown(*S_GLator_EffectCommonData.get()); | |
| S_GLator_EffectCommonData.reset(); | |
| S_ResourcePath.clear(); | |
| if (in_data->sequence_data) { | |
| PF_DISPOSE_HANDLE(in_data->sequence_data); | |
| out_data->sequence_data = NULL; | |
| } | |
| } | |
| catch(PF_Err& thrown_err) | |
| { | |
| err = thrown_err; | |
| } | |
| catch (...) | |
| { | |
| err = PF_Err_OUT_OF_MEMORY; | |
| } | |
| return err; | |
| } | |
| static PF_Err | |
| PreRender( | |
| PF_InData *in_data, | |
| PF_OutData *out_data, | |
| PF_PreRenderExtra *extra) | |
| { | |
| PF_Err err = PF_Err_NONE, | |
| err2 = PF_Err_NONE; | |
| PF_ParamDef slider_param; | |
| PF_RenderRequest req = extra->input->output_request; | |
| PF_CheckoutResult in_result; | |
| AEFX_CLR_STRUCT(slider_param); | |
| ERR(PF_CHECKOUT_PARAM(in_data, | |
| GLATOR_SLIDER, | |
| in_data->current_time, | |
| in_data->time_step, | |
| in_data->time_scale, | |
| &slider_param)); | |
| ERR(extra->cb->checkout_layer(in_data->effect_ref, | |
| GLATOR_INPUT, | |
| GLATOR_INPUT, | |
| &req, | |
| in_data->current_time, | |
| in_data->time_step, | |
| in_data->time_scale, | |
| &in_result)); | |
| if (!err){ | |
| UnionLRect(&in_result.result_rect, &extra->output->result_rect); | |
| UnionLRect(&in_result.max_result_rect, &extra->output->max_result_rect); | |
| } | |
| ERR2(PF_CHECKIN_PARAM(in_data, &slider_param)); | |
| return err; | |
| } | |
| static PF_Err | |
| SmartRender( | |
| PF_InData *in_data, | |
| PF_OutData *out_data, | |
| PF_SmartRenderExtra *extra) | |
| { | |
| PF_Err err = PF_Err_NONE, | |
| err2 = PF_Err_NONE; | |
| PF_EffectWorld *input_worldP = NULL, | |
| *output_worldP = NULL; | |
| PF_WorldSuite2 *wsP = NULL; | |
| PF_PixelFormat format = PF_PixelFormat_INVALID; | |
| PF_FpLong sliderVal = 0; | |
| AEGP_SuiteHandler suites(in_data->pica_basicP); | |
| PF_ParamDef slider_param; | |
| AEFX_CLR_STRUCT(slider_param); | |
| ERR(PF_CHECKOUT_PARAM(in_data, | |
| GLATOR_SLIDER, | |
| in_data->current_time, | |
| in_data->time_step, | |
| in_data->time_scale, | |
| &slider_param)); | |
| if (!err){ | |
| sliderVal = slider_param.u.fd.value / 100.0f; | |
| } | |
| ERR((extra->cb->checkout_layer_pixels(in_data->effect_ref, GLATOR_INPUT, &input_worldP))); | |
| ERR(extra->cb->checkout_output(in_data->effect_ref, &output_worldP)); | |
| ERR(AEFX_AcquireSuite(in_data, | |
| out_data, | |
| kPFWorldSuite, | |
| kPFWorldSuiteVersion2, | |
| "Couldn't load suite.", | |
| (void**)&wsP)); | |
| if (!err){ | |
| try | |
| { | |
| // always restore back AE's own OGL context | |
| SaveRestoreOGLContext oSavedContext; | |
| // our render specific context (one per thread) | |
| AESDK_OpenGL::AESDK_OpenGL_EffectRenderDataPtr renderContext = GetCurrentRenderContext(); | |
| if (!renderContext->mInitialized) { | |
| //Now comes the OpenGL part - OS specific loading to start with | |
| AESDK_OpenGL_Startup(*renderContext.get(), S_GLator_EffectCommonData.get()); | |
| renderContext->mInitialized = true; | |
| } | |
| renderContext->SetPluginContext(); | |
| // - Gremedy OpenGL debugger | |
| // - Example of using a OpenGL extension | |
| bool hasGremedy = renderContext->mExtensions.find(gl::GLextension::GL_GREMEDY_frame_terminator) != renderContext->mExtensions.end(); | |
| A_long widthL = input_worldP->width; | |
| A_long heightL = input_worldP->height; | |
| //loading OpenGL resources | |
| AESDK_OpenGL_InitResources(*renderContext.get(), widthL, heightL, S_ResourcePath); | |
| CHECK(wsP->PF_GetPixelFormat(input_worldP, &format)); | |
| // upload the input world to a texture | |
| size_t pixSize; | |
| gl::GLenum glFmt; | |
| float multiplier16bit; | |
| gl::GLuint inputFrameTexture = UploadTexture(suites, format, input_worldP, output_worldP, in_data, pixSize, glFmt, multiplier16bit); | |
| // Set up the frame-buffer object just like a window. | |
| AESDK_OpenGL_MakeReadyToRender(*renderContext.get(), renderContext->mOutputFrameTexture); | |
| ReportIfErrorFramebuffer(in_data, out_data); | |
| glViewport(0, 0, widthL, heightL); | |
| glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| // - simply blend the texture inside the frame buffer | |
| // - TODO: hack your own shader there | |
| RenderGL(renderContext, widthL, heightL, inputFrameTexture, sliderVal, multiplier16bit); | |
| // - we toggle PBO textures (we use the PBO we just created as an input) | |
| AESDK_OpenGL_MakeReadyToRender(*renderContext.get(), inputFrameTexture); | |
| ReportIfErrorFramebuffer(in_data, out_data); | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| // swizzle using the previous output | |
| SwizzleGL(renderContext, widthL, heightL, renderContext->mOutputFrameTexture, multiplier16bit); | |
| if (hasGremedy) { | |
| gl::glFrameTerminatorGREMEDY(); | |
| } | |
| // - get back to CPU the result, and inside the output world | |
| DownloadTexture(renderContext, suites, input_worldP, output_worldP, in_data, | |
| format, pixSize, glFmt); | |
| glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
| glBindTexture(GL_TEXTURE_2D, 0); | |
| glDeleteTextures(1, &inputFrameTexture); | |
| } | |
| catch (PF_Err& thrown_err) | |
| { | |
| err = thrown_err; | |
| } | |
| catch (...) | |
| { | |
| err = PF_Err_OUT_OF_MEMORY; | |
| } | |
| } | |
| // If you have PF_ABORT or PF_PROG higher up, you must set | |
| // the AE context back before calling them, and then take it back again | |
| // if you want to call some more OpenGL. | |
| ERR(PF_ABORT(in_data)); | |
| ERR2(AEFX_ReleaseSuite(in_data, | |
| out_data, | |
| kPFWorldSuite, | |
| kPFWorldSuiteVersion2, | |
| "Couldn't release suite.")); | |
| ERR2(PF_CHECKIN_PARAM(in_data, &slider_param)); | |
| ERR2(extra->cb->checkin_layer_pixels(in_data->effect_ref, GLATOR_INPUT)); | |
| return err; | |
| } | |
| extern "C" DllExport | |
| PF_Err PluginDataEntryFunction( | |
| PF_PluginDataPtr inPtr, | |
| PF_PluginDataCB inPluginDataCallBackPtr, | |
| SPBasicSuite* inSPBasicSuitePtr, | |
| const char* inHostName, | |
| const char* inHostVersion) | |
| { | |
| PF_Err result = PF_Err_INVALID_CALLBACK; | |
| result = PF_REGISTER_EFFECT( | |
| inPtr, | |
| inPluginDataCallBackPtr, | |
| "GLator", // Name | |
| "ADBE GLator", // Match Name | |
| "Sample Plug-ins", // Category | |
| AE_RESERVED_INFO); // Reserved Info | |
| return result; | |
| } | |
| PF_Err | |
| EffectMain( | |
| PF_Cmd cmd, | |
| PF_InData *in_data, | |
| PF_OutData *out_data, | |
| PF_ParamDef *params[], | |
| PF_LayerDef *output, | |
| void *extra) | |
| { | |
| /******************* | |
| Important Notice 06/02/2020 | |
| OpenGL was deprecated on macOS 10.14 with Apple asking all developers to move to using the Metal framework. | |
| As such we are recommending cross-platform plugins are no longer developed directly against OpenGL. | |
| For GPU-based plugin development, please refer to the SDK_Invert_ProcAmp SDK sample on how to use GPU rendering with the plugin SDK. | |
| This plugin is kept only for reference. | |
| *******************/ | |
| PF_Err err = PF_Err_NONE; | |
| try { | |
| switch (cmd) { | |
| case PF_Cmd_ABOUT: | |
| err = About(in_data, | |
| out_data, | |
| params, | |
| output); | |
| break; | |
| case PF_Cmd_GLOBAL_SETUP: | |
| err = GlobalSetup( in_data, | |
| out_data, | |
| params, | |
| output); | |
| break; | |
| case PF_Cmd_PARAMS_SETUP: | |
| err = ParamsSetup( in_data, | |
| out_data, | |
| params, | |
| output); | |
| break; | |
| case PF_Cmd_GLOBAL_SETDOWN: | |
| err = GlobalSetdown( in_data, | |
| out_data, | |
| params, | |
| output); | |
| break; | |
| case PF_Cmd_SMART_PRE_RENDER: | |
| err = PreRender(in_data, out_data, reinterpret_cast<PF_PreRenderExtra*>(extra)); | |
| break; | |
| case PF_Cmd_SMART_RENDER: | |
| err = SmartRender(in_data, out_data, reinterpret_cast<PF_SmartRenderExtra*>(extra)); | |
| break; | |
| } | |
| } | |
| catch(PF_Err &thrown_err){ | |
| err = thrown_err; | |
| } | |
| return err; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment