Video.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /**
  2. * Copyright (c) 2006-2016 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "Video.h"
  21. // LOVE
  22. #include "Shader.h"
  23. namespace love
  24. {
  25. namespace graphics
  26. {
  27. namespace opengl
  28. {
  29. Video::Video(love::video::VideoStream *stream)
  30. : stream(stream)
  31. , filter(Texture::getDefaultFilter())
  32. {
  33. filter.mipmap = Texture::FILTER_NONE;
  34. stream->fillBackBuffer();
  35. for (int i = 0; i < 4; i++)
  36. vertices[i].r = vertices[i].g = vertices[i].b = vertices[i].a = 255;
  37. // Vertices are ordered for use with triangle strips:
  38. // 0----2
  39. // | / |
  40. // | / |
  41. // 1----3
  42. vertices[0].x = 0.0f;
  43. vertices[0].y = 0.0f;
  44. vertices[1].x = 0.0f;
  45. vertices[1].y = (float) stream->getHeight();
  46. vertices[2].x = (float) stream->getWidth();
  47. vertices[2].y = 0.0f;
  48. vertices[3].x = (float) stream->getWidth();
  49. vertices[3].y = (float) stream->getHeight();
  50. vertices[0].s = 0.0f;
  51. vertices[0].t = 0.0f;
  52. vertices[1].s = 0.0f;
  53. vertices[1].t = 1.0f;
  54. vertices[2].s = 1.0f;
  55. vertices[2].t = 0.0f;
  56. vertices[3].s = 1.0f;
  57. vertices[3].t = 1.0f;
  58. loadVolatile();
  59. }
  60. Video::~Video()
  61. {
  62. unloadVolatile();
  63. }
  64. bool Video::loadVolatile()
  65. {
  66. glGenTextures(3, &textures[0]);
  67. // Create the textures using the initial frame data.
  68. auto frame = (const love::video::VideoStream::Frame*) stream->getFrontBuffer();
  69. int widths[3] = {frame->yw, frame->cw, frame->cw};
  70. int heights[3] = {frame->yh, frame->ch, frame->ch};
  71. const unsigned char *data[3] = {frame->yplane, frame->cbplane, frame->crplane};
  72. Texture::Wrap wrap; // Clamp wrap mode.
  73. for (int i = 0; i < 3; i++)
  74. {
  75. gl.bindTextureToUnit(textures[i], 0, false);
  76. gl.setTextureFilter(filter);
  77. gl.setTextureWrap(wrap);
  78. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, widths[i], heights[i], 0,
  79. GL_LUMINANCE, GL_UNSIGNED_BYTE, data[i]);
  80. }
  81. return true;
  82. }
  83. void Video::unloadVolatile()
  84. {
  85. for (int i = 0; i < 3; i++)
  86. {
  87. gl.deleteTexture(textures[i]);
  88. textures[i] = 0;
  89. }
  90. }
  91. love::video::VideoStream *Video::getStream()
  92. {
  93. return stream;
  94. }
  95. void Video::draw(const Matrix4 &m)
  96. {
  97. update();
  98. Shader *shader = Shader::current;
  99. bool defaultShader = (shader == Shader::defaultShader);
  100. if (defaultShader)
  101. {
  102. // If we're still using the default shader, substitute the video version
  103. Shader::defaultVideoShader->attach();
  104. shader = Shader::defaultVideoShader;
  105. }
  106. shader->setVideoTextures(textures[0], textures[1], textures[2]);
  107. OpenGL::TempTransform transform(gl);
  108. transform.get() *= m;
  109. gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD);
  110. gl.bindBuffer(BUFFER_VERTEX, 0);
  111. glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertices[0].x);
  112. glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertices[0].s);
  113. gl.prepareDraw();
  114. gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
  115. // If we were using the default shader, reattach it
  116. if (defaultShader)
  117. Shader::defaultShader->attach();
  118. }
  119. void Video::update()
  120. {
  121. bool bufferschanged = stream->swapBuffers();
  122. stream->fillBackBuffer();
  123. if (bufferschanged)
  124. {
  125. auto frame = (const love::video::VideoStream::Frame*) stream->getFrontBuffer();
  126. int widths[3] = {frame->yw, frame->cw, frame->cw};
  127. int heights[3] = {frame->yh, frame->ch, frame->ch};
  128. const unsigned char *data[3] = {frame->yplane, frame->cbplane, frame->crplane};
  129. for (int i = 0; i < 3; i++)
  130. {
  131. gl.bindTextureToUnit(textures[i], 0, false);
  132. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widths[i], heights[i],
  133. GL_LUMINANCE, GL_UNSIGNED_BYTE, data[i]);
  134. }
  135. }
  136. }
  137. love::audio::Source *Video::getSource()
  138. {
  139. return source;
  140. }
  141. void Video::setSource(love::audio::Source *source)
  142. {
  143. this->source = source;
  144. }
  145. int Video::getWidth() const
  146. {
  147. return stream->getWidth();
  148. }
  149. int Video::getHeight() const
  150. {
  151. return stream->getHeight();
  152. }
  153. void Video::setFilter(const Texture::Filter &f)
  154. {
  155. if (!Texture::validateFilter(f, false))
  156. throw love::Exception("Invalid texture filter.");
  157. filter = f;
  158. for (int i = 0; i < 3; i++)
  159. {
  160. gl.bindTextureToUnit(textures[i], 0, false);
  161. gl.setTextureFilter(filter);
  162. }
  163. }
  164. const Texture::Filter &Video::getFilter() const
  165. {
  166. return filter;
  167. }
  168. } // opengl
  169. } // graphics
  170. } // love