Video.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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.bindTexture(textures[i]);
  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. glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertices[0].x);
  111. glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &vertices[0].s);
  112. gl.prepareDraw();
  113. gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
  114. // If we were using the default shader, reattach it
  115. if (defaultShader)
  116. Shader::defaultShader->attach();
  117. }
  118. void Video::update()
  119. {
  120. bool bufferschanged = stream->swapBuffers();
  121. stream->fillBackBuffer();
  122. if (bufferschanged)
  123. {
  124. auto frame = (const love::video::VideoStream::Frame*) stream->getFrontBuffer();
  125. int widths[3] = {frame->yw, frame->cw, frame->cw};
  126. int heights[3] = {frame->yh, frame->ch, frame->ch};
  127. const unsigned char *data[3] = {frame->yplane, frame->cbplane, frame->crplane};
  128. for (int i = 0; i < 3; i++)
  129. {
  130. gl.bindTexture(textures[i]);
  131. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widths[i], heights[i],
  132. GL_LUMINANCE, GL_UNSIGNED_BYTE, data[i]);
  133. }
  134. }
  135. }
  136. love::audio::Source *Video::getSource()
  137. {
  138. return source;
  139. }
  140. void Video::setSource(love::audio::Source *source)
  141. {
  142. this->source = source;
  143. }
  144. int Video::getWidth() const
  145. {
  146. return stream->getWidth();
  147. }
  148. int Video::getHeight() const
  149. {
  150. return stream->getHeight();
  151. }
  152. void Video::setFilter(const Texture::Filter &f)
  153. {
  154. if (!Texture::validateFilter(f, false))
  155. throw love::Exception("Invalid texture filter.");
  156. filter = f;
  157. for (int i = 0; i < 3; i++)
  158. {
  159. gl.bindTexture(textures[i]);
  160. gl.setTextureFilter(filter);
  161. }
  162. }
  163. const Texture::Filter &Video::getFilter() const
  164. {
  165. return filter;
  166. }
  167. } // opengl
  168. } // graphics
  169. } // love