forked from mia/Aegisub
Mostly operational pixel shaded YV12->RGB32 conversion. (needs glew for now)
Originally committed to SVN as r899.
This commit is contained in:
parent
9a292d6091
commit
3b9afa126e
10 changed files with 252 additions and 37 deletions
|
@ -36,10 +36,18 @@
|
|||
|
||||
///////////
|
||||
// Headers
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include "gl_wrap.h"
|
||||
|
||||
|
||||
////////////////
|
||||
// GLEW library
|
||||
#if __VISUALC__ >= 1200
|
||||
#pragma comment(lib,"glew32.lib")
|
||||
#endif
|
||||
|
||||
|
||||
/////////////
|
||||
// Draw line
|
||||
void OpenGLWrapper::DrawLine(float x1,float y1,float x2,float y2) {
|
||||
|
@ -222,3 +230,153 @@ void OpenGLWrapper::SetModeFill() {
|
|||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////
|
||||
// Are shaders available?
|
||||
bool OpenGLWrapper::ShadersAvailable() {
|
||||
if (GLEW_VERSION_2_0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
///////////////////
|
||||
// Initialize GLEW
|
||||
void OpenGLWrapper::InitializeGLEW() {
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
glewInit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////
|
||||
// Set current shader
|
||||
void OpenGLWrapper::SetShader(GLuint i) {
|
||||
InitializeGLEW();
|
||||
glUseProgram(i);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////
|
||||
// Destroy shader program
|
||||
void OpenGLWrapper::DestroyShaderProgram(GLuint i) {
|
||||
InitializeGLEW();
|
||||
SetShader(0);
|
||||
glDeleteProgram(i);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Create shader program from vertex and pixel shaders
|
||||
GLuint OpenGLWrapper::CreateShaderProgram(GLuint vertex,GLuint pixel) {
|
||||
// Create instance
|
||||
InitializeGLEW();
|
||||
GLuint program = glCreateProgram();
|
||||
|
||||
// Attach shaders
|
||||
glAttachShader(program,vertex);
|
||||
glAttachShader(program,pixel);
|
||||
|
||||
// Link
|
||||
glLinkProgram(program);
|
||||
|
||||
// Return
|
||||
return program;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Create standard Vertex shader
|
||||
GLuint OpenGLWrapper::CreateStandardVertexShader() {
|
||||
// Create instance
|
||||
InitializeGLEW();
|
||||
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
|
||||
// Read source
|
||||
char source[] =
|
||||
"void main() {\n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
||||
" gl_Position = ftransform();\n"
|
||||
"}";
|
||||
const GLchar *src = source;
|
||||
glShaderSource(shader,1,&src,NULL);
|
||||
|
||||
// Compile
|
||||
glCompileShader(shader);
|
||||
|
||||
// Return
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
// Create YV12->RGB32 Pixel Shader
|
||||
GLuint OpenGLWrapper::CreateYV12PixelShader() {
|
||||
// Create instance
|
||||
InitializeGLEW();
|
||||
GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
// Read source
|
||||
char source[] =
|
||||
"uniform sampler2D tex;\n"
|
||||
"uniform vec2 off1;\n"
|
||||
"uniform vec2 off2;\n"
|
||||
"\n"
|
||||
"void main() {\n"
|
||||
" vec2 pos = gl_TexCoord[0].st;\n"
|
||||
" vec4 y_bias = vec4(-0.063,-0.063,-0.063,0.0);\n"
|
||||
" vec4 y_mult = vec4(1.164,1.164,1.164,1.0);\n"
|
||||
" vec4 color_y = (texture2D(tex,pos) + y_bias) * y_mult;\n"
|
||||
" pos *= 0.5;\n"
|
||||
" vec4 uv_bias = vec4(-0.5,-0.5,-0.5,0.0);\n"
|
||||
" vec4 uv_mult = vec4(0.0,-0.391,2.018,1.0);\n"
|
||||
//" vec4 uv_mult = vec4(0.0,-0.344,1.770,1.0);\n"
|
||||
" vec4 color_u = (texture2D(tex,pos + off1) + uv_bias) * uv_mult;\n"
|
||||
" uv_mult = vec4(1.596,-0.813,0.0,1.0);\n"
|
||||
//" uv_mult = vec4(1.403,-0.714,0.0,1.0);\n"
|
||||
" vec4 color_v = (texture2D(tex,pos + off2) + uv_bias) * uv_mult;\n"
|
||||
" gl_FragColor = color_y + color_u + color_v;\n"
|
||||
"}";
|
||||
const GLchar *src = source;
|
||||
glShaderSource(shader,1,&src,NULL);
|
||||
|
||||
// Compile
|
||||
glCompileShader(shader);
|
||||
|
||||
// Return
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
// Create YV12->RGB32 Shader Program
|
||||
GLuint OpenGLWrapper::CreateYV12Shader(float tw,float th) {
|
||||
// Create vertex shader
|
||||
GLuint ver = OpenGLWrapper::CreateStandardVertexShader();
|
||||
if (glGetError() != 0) throw _T("Error creating generic vertex shader");
|
||||
|
||||
// Create pixel shader
|
||||
GLuint pix = OpenGLWrapper::CreateYV12PixelShader();
|
||||
if (glGetError() != 0) throw _T("Error creating YV12 pixel shader");
|
||||
|
||||
// Create program
|
||||
GLuint program = OpenGLWrapper::CreateShaderProgram(ver,pix);
|
||||
if (glGetError() != 0) throw _T("Error creating shader program");
|
||||
|
||||
// Set shader
|
||||
OpenGLWrapper::SetShader(program);
|
||||
if (glGetError() != 0) throw _T("Error setting shader");
|
||||
|
||||
// Set uniform variables
|
||||
GLuint address = glGetUniformLocation(program,"tex");
|
||||
glUniform1i(address, 0);
|
||||
address = glGetUniformLocation(program,"off1");
|
||||
glUniform2f(address, 0.0f, th);
|
||||
address = glGetUniformLocation(program,"off2");
|
||||
glUniform2f(address, tw*0.5f, th);
|
||||
|
||||
// Return shader
|
||||
return program;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,11 @@ private:
|
|||
float r2,g2,b2,a2;
|
||||
int lw;
|
||||
|
||||
static void InitializeGLEW();
|
||||
static GLuint CreateStandardVertexShader();
|
||||
static GLuint CreateYV12PixelShader();
|
||||
static GLuint CreateShaderProgram(GLuint vertex,GLuint pixel);
|
||||
|
||||
public:
|
||||
void SetLineColour(wxColour col,float alpha=1.0f,int width=1);
|
||||
void SetFillColour(wxColour col,float alpha=1.0f);
|
||||
|
@ -55,4 +60,9 @@ public:
|
|||
void DrawCircle(float x,float y,float radius) { DrawEllipse(x,y,radius,radius); }
|
||||
void DrawRectangle(float x1,float y1,float x2,float y2);
|
||||
void DrawRing(float x,float y,float r1,float r2,float ar=1.0f,float arcStart=0.0f,float arcEnd=0.0f);
|
||||
|
||||
static bool ShadersAvailable();
|
||||
static void SetShader(GLuint i);
|
||||
static void DestroyShaderProgram(GLuint i);
|
||||
static GLuint CreateYV12Shader(float tw,float th);
|
||||
};
|
||||
|
|
|
@ -148,6 +148,7 @@ void OptionsManager::LoadDefaults() {
|
|||
SetBool(_T("Allow Ancient Avisynth"),false);
|
||||
SetText(_T("Video Provider"),_T("Avisynth"));
|
||||
SetText(_T("Subtitles Provider"),_T("CSRI"));
|
||||
SetBool(_T("Video Use Pixel Shaders"),false);
|
||||
|
||||
// Audio Options
|
||||
SetBool(_T("Audio Next Line on Commit"),true);
|
||||
|
|
|
@ -78,6 +78,9 @@
|
|||
#include <wx/event.h>
|
||||
#include <wx/wxscintilla.h>
|
||||
#include <wx/string.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <wx/glcanvas.h>
|
||||
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "video_slider.h"
|
||||
#include "video_box.h"
|
||||
#include "utils.h"
|
||||
#include "gl_wrap.h"
|
||||
|
||||
|
||||
///////
|
||||
|
@ -93,6 +94,7 @@ VideoContext::VideoContext() {
|
|||
glContext = NULL;
|
||||
lastTex = 0;
|
||||
lastFrame = -1;
|
||||
yv12shader = 0;
|
||||
|
||||
// Set options
|
||||
audio = NULL;
|
||||
|
@ -142,6 +144,12 @@ void VideoContext::Clear() {
|
|||
/////////
|
||||
// Reset
|
||||
void VideoContext::Reset() {
|
||||
// Reset shader
|
||||
if (yv12shader) {
|
||||
OpenGLWrapper::DestroyShaderProgram(yv12shader);
|
||||
yv12shader = 0;
|
||||
}
|
||||
|
||||
// Clear keyframes
|
||||
KeyFrames.Clear();
|
||||
keyFramesLoaded = false;
|
||||
|
@ -426,6 +434,7 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
|
|||
glShadeModel(GL_FLAT);
|
||||
|
||||
// Generate texture with GL
|
||||
//glActiveTexture(GL_TEXTURE0);
|
||||
glGenTextures(1, &lastTex);
|
||||
if (glGetError() != 0) throw _T("Error generating texture.");
|
||||
glBindTexture(GL_TEXTURE_2D, lastTex);
|
||||
|
@ -439,9 +448,9 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
|
|||
|
||||
// Load image data into texture
|
||||
int height = frame.h;
|
||||
if (frame.format == FORMAT_YV12) height = frame.h * 3 / 2;
|
||||
if (frame.format == FORMAT_YV12) height = height * 3 / 2;
|
||||
int tw = SmallestPowerOf2(frame.w);
|
||||
int th = SmallestPowerOf2(frame.h);
|
||||
int th = SmallestPowerOf2(height);
|
||||
texW = float(frame.w)/float(tw);
|
||||
texH = float(frame.h)/float(th);
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,tw,th,0,format,GL_UNSIGNED_BYTE,NULL);
|
||||
|
@ -454,6 +463,11 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
|
|||
// Set priority
|
||||
float priority = 1.0f;
|
||||
glPrioritizeTextures(1,&lastTex,&priority);
|
||||
|
||||
// Create shader if necessary
|
||||
if (frame.format == FORMAT_YV12 && yv12shader == 0) {
|
||||
yv12shader = OpenGLWrapper::CreateYV12Shader(texW,texH);
|
||||
}
|
||||
}
|
||||
|
||||
// Load texture data
|
||||
|
@ -730,3 +744,10 @@ void VideoContext::SetAspectRatio(int _type, double value) {
|
|||
arValue = value;
|
||||
UpdateDisplays(true);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Enable or disable shader
|
||||
void VideoContext::SetShader(bool enabled) {
|
||||
OpenGLWrapper::SetShader(enabled ? yv12shader : 0);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ private:
|
|||
std::list<VideoDisplay*> displayList;
|
||||
|
||||
GLuint lastTex;
|
||||
GLuint yv12shader;
|
||||
int lastFrame;
|
||||
wxGLContext *glContext;
|
||||
VideoFrameFormat vidFormat;
|
||||
|
@ -130,6 +131,7 @@ public:
|
|||
float GetTexW() { return texW; }
|
||||
float GetTexH() { return texH; }
|
||||
VideoFrameFormat GetFormat() { return vidFormat; }
|
||||
void SetShader(bool enabled);
|
||||
|
||||
bool IsLoaded() { return loaded; }
|
||||
bool IsPlaying() { return isPlaying; }
|
||||
|
|
|
@ -203,8 +203,9 @@ void VideoDisplay::Render() {
|
|||
float left = 0.0;
|
||||
float right = context->GetTexW();
|
||||
|
||||
// Draw interleaved frame or luma of YV12
|
||||
// Draw frame
|
||||
glDisable(GL_BLEND);
|
||||
context->SetShader(true);
|
||||
glBindTexture(GL_TEXTURE_2D, VideoContext::Get()->GetFrameAsTexture(-1));
|
||||
glColor4f(1.0f,1.0f,1.0f,1.0f);
|
||||
glBegin(GL_QUADS);
|
||||
|
@ -221,11 +222,7 @@ void VideoDisplay::Render() {
|
|||
glTexCoord2f(right,top);
|
||||
glVertex2f(sw,0);
|
||||
glEnd();
|
||||
|
||||
// Draw UV planes
|
||||
if (context->GetFormat() == FORMAT_YV12) {
|
||||
|
||||
}
|
||||
context->SetShader(false);
|
||||
|
||||
// Draw overlay
|
||||
visual->DrawOverlay();
|
||||
|
|
|
@ -188,6 +188,16 @@ void VideoDisplayVisual::DrawOverlay() {
|
|||
}
|
||||
else GetLineScale(diag,scalX,scalY);
|
||||
|
||||
// Get angle
|
||||
GetLineRotation(diag,rx,ry,rz);
|
||||
if (isCur) {
|
||||
if (mode == 2) rz = curAngle;
|
||||
else if (mode == 3) {
|
||||
rx = curAngle;
|
||||
ry = curAngle2;
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse over?
|
||||
if (diag == diagHigh) {
|
||||
high = true;
|
||||
|
@ -225,16 +235,6 @@ void VideoDisplayVisual::DrawOverlay() {
|
|||
DrawLine(dx,dy-16,dx,dy+16);
|
||||
DrawLine(dx-16,dy,dx+16,dy);
|
||||
|
||||
// Get angle
|
||||
GetLineRotation(diag,rx,ry,rz);
|
||||
if (isCur) {
|
||||
if (mode == 2) rz = curAngle;
|
||||
else {
|
||||
rx = curAngle;
|
||||
ry = curAngle2;
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate Z
|
||||
if (mode == 2) {
|
||||
// Transform
|
||||
|
@ -387,37 +387,54 @@ void VideoDisplayVisual::DrawOverlay() {
|
|||
|
||||
// Scale
|
||||
if (mode == 4) {
|
||||
// Scale parameters
|
||||
// Set dx/dy
|
||||
int len = 160;
|
||||
int lenx = int(1.6 * scalX);
|
||||
int leny = int(1.6 * scalY);
|
||||
dx = MID(len/2+10,dx,sw-len/2-30);
|
||||
dy = MID(len/2+10,dy,sh-len/2-30);
|
||||
int drawX = dx + len/2 + 10;
|
||||
int drawY = dy + len/2 + 10;
|
||||
|
||||
// Transform grid
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glTranslatef(dx,dy,0.0f);
|
||||
float matrix[16] = { 2500, 0, 0, 0, 0, 2500, 0, 0, 0, 0, 1, 1, 0, 0, 2500, 2500 };
|
||||
glMultMatrixf(matrix);
|
||||
glScalef(1.0f,1.0f,8.0f);
|
||||
if (ry != 0.0f) glRotatef(ry,0.0f,-1.0f,0.0f);
|
||||
if (rx != 0.0f) glRotatef(rx,-1.0f,0.0f,0.0f);
|
||||
if (rz != 0.0f) glRotatef(rz,0.0f,0.0f,-1.0f);
|
||||
|
||||
// Scale parameters
|
||||
int lenx = int(1.6 * scalX);
|
||||
int leny = int(1.6 * scalY);
|
||||
int drawX = len/2 + 10;
|
||||
int drawY = len/2 + 10;
|
||||
|
||||
// Draw length markers
|
||||
SetLineColour(colour[3],1.0f,2);
|
||||
DrawLine(dx-lenx/2,drawY+10,dx+lenx/2,drawY+10);
|
||||
DrawLine(drawX+10,dy-leny/2,drawX+10,dy+leny/2);
|
||||
DrawLine(-lenx/2,drawY+10,lenx/2,drawY+10);
|
||||
DrawLine(drawX+10,-leny/2,drawX+10,leny/2);
|
||||
SetLineColour(colour[0],1.0f,1);
|
||||
SetFillColour(colour[brushCol],0.3f);
|
||||
DrawCircle(dx+lenx/2,drawY+10,4);
|
||||
DrawCircle(drawX+10,dy-leny/2,4);
|
||||
DrawCircle(lenx/2,drawY+10,4);
|
||||
DrawCircle(drawX+10,-leny/2,4);
|
||||
|
||||
// Draw horizontal scale
|
||||
SetLineColour(colour[0],1.0f,1);
|
||||
DrawRectangle(dx-len/2,drawY,dx+len/2+1,drawY+5);
|
||||
DrawRectangle(-len/2,drawY,len/2+1,drawY+5);
|
||||
SetLineColour(colour[0],1.0f,2);
|
||||
DrawLine(dx-len/2+1,drawY+5,dx-len/2+1,drawY+15);
|
||||
DrawLine(dx+len/2,drawY+5,dx+len/2,drawY+15);
|
||||
DrawLine(-len/2+1,drawY+5,-len/2+1,drawY+15);
|
||||
DrawLine(len/2,drawY+5,len/2,drawY+15);
|
||||
|
||||
// Draw vertical scale
|
||||
SetLineColour(colour[0],1.0f,1);
|
||||
DrawRectangle(drawX,dy-len/2,drawX+5,dy+len/2+1);
|
||||
DrawRectangle(drawX,-len/2,drawX+5,len/2+1);
|
||||
SetLineColour(colour[0],1.0f,2);
|
||||
DrawLine(drawX+5,dy-len/2+1,drawX+15,dy-len/2+1);
|
||||
DrawLine(drawX+5,dy+len/2,drawX+15,dy+len/2);
|
||||
DrawLine(drawX+5,-len/2+1,drawX+15,-len/2+1);
|
||||
DrawLine(drawX+5,len/2,drawX+15,len/2);
|
||||
|
||||
// Restore gl's state
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// Clip
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "main.h"
|
||||
#include "vfr.h"
|
||||
#include "ass_file.h"
|
||||
#include "gl_wrap.h"
|
||||
|
||||
|
||||
////////////
|
||||
|
@ -293,8 +294,10 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
|||
}
|
||||
|
||||
// Convert to RGB32
|
||||
script = env->Invoke("ConvertToRGB32", script);
|
||||
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Converted to RGB32"));
|
||||
if (OpenGLWrapper::ShadersAvailable() && !Options.AsBool(_T("Video Use Pixel Shaders"))) {
|
||||
script = env->Invoke("ConvertToRGB32", script);
|
||||
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Converted to RGB32"));
|
||||
}
|
||||
|
||||
// Directshow
|
||||
//if (usedDirectshow) wxMessageBox(_T("Warning! The file is being opened using Avisynth's DirectShowSource, which has unreliable seeking. Frame numbers might not match the real number. PROCEED AT YOUR OWN RISK!"),_T("DirectShowSource warning"),wxICON_EXCLAMATION);
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
#include "utils.h"
|
||||
#include "vfr.h"
|
||||
#include "videosink.h"
|
||||
#include "gl_wrap.h"
|
||||
#include "options.h"
|
||||
|
||||
|
||||
///////////////////////
|
||||
|
@ -292,8 +294,9 @@ HRESULT DirectShowVideoProvider::OpenVideo(wxString _filename) {
|
|||
if (!sink2) return E_NOINTERFACE;
|
||||
|
||||
// Set allowed types for sink
|
||||
//sink->SetAllowedTypes(IVS_RGB32|IVS_YV12|IVS_YUY2);
|
||||
sink->SetAllowedTypes(IVS_RGB24);
|
||||
unsigned int types = IVS_RGB24 | IVS_RGB32;
|
||||
if (OpenGLWrapper::ShadersAvailable() && !Options.AsBool(_T("Video Use Pixel Shaders"))) types = types | IVS_YV12;
|
||||
sink->SetAllowedTypes(types);
|
||||
|
||||
// Pass the event to sink, so it gets set when a frame is available
|
||||
ResetEvent(m_hFrameReady);
|
||||
|
|
Loading…
Reference in a new issue