~ubuntu-branches/debian/experimental/mednafen/experimental

« back to all changes in this revision

Viewing changes to src/video/Deinterlacer.cpp

  • Committer: Package Import Robot
  • Author(s): Stephen Kitt
  • Date: 2014-11-08 11:36:07 UTC
  • mfrom: (1.2.18) (10.1.16 sid)
  • Revision ID: package-import@ubuntu.com-20141108113607-3lbwsamqqhrso4hp
Tags: 0.9.36.5-1
* New upstream release, uploaded to expermiental for the Jessie freeze.
* Standards-Version 3.9.6, no change required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Mednafen - Multi-system Emulator
 
2
 *
 
3
 * This program is free software; you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License as published by
 
5
 * the Free Software Foundation; either version 2 of the License, or
 
6
 * (at your option) any later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program; if not, write to the Free Software
 
15
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 */
 
17
 
1
18
#include "video-common.h"
2
19
#include "Deinterlacer.h"
3
20
 
4
 
enum
5
 
{
6
 
 DEINT_BOB_OFFSET = 0,  // Code will fall-through to this case under certain conditions, too.
7
 
 DEINT_BOB,
8
 
 DEINT_WEAVE,
9
 
};
10
 
 
11
 
static const unsigned DeintType = DEINT_WEAVE;
12
 
 
13
 
Deinterlacer::Deinterlacer()
14
 
{
15
 
 FieldBuffer = NULL;
16
 
 
17
 
 StateValid = false;
18
 
 PrevHeight = 0;
 
21
Deinterlacer::Deinterlacer() : FieldBuffer(NULL), StateValid(false), DeintType(DEINT_WEAVE)
 
22
{
 
23
 PrevDRect.x = 0;
 
24
 PrevDRect.y = 0;
 
25
 
 
26
 PrevDRect.w = 0;
 
27
 PrevDRect.h = 0;
19
28
}
20
29
 
21
30
Deinterlacer::~Deinterlacer()
27
36
 }
28
37
}
29
38
 
30
 
#if 0
31
39
void Deinterlacer::SetType(unsigned dt)
32
40
{
33
41
 if(DeintType != dt)
43
51
  StateValid = false;
44
52
 }
45
53
}
46
 
#endif
47
54
 
48
55
template<typename T>
49
 
void Deinterlacer::InternalProcess(MDFN_Surface *surface, const MDFN_Rect &DisplayRect, MDFN_Rect *LineWidths, const bool field)
 
56
void Deinterlacer::InternalProcess(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field)
50
57
{
51
58
 //
52
59
 // We need to output with LineWidths as always being valid to handle the case of horizontal resolution change between fields
53
60
 // while in interlace mode, so clear the first LineWidths entry if it's == ~0, and
54
61
 // [...]
55
 
 const bool LineWidths_In_Valid = (LineWidths[0].w != ~0);
 
62
 const bool LineWidths_In_Valid = (LineWidths[0] != ~0);
 
63
 const bool WeaveGood = (StateValid && PrevDRect.h == DisplayRect.h && DeintType == DEINT_WEAVE);
 
64
 //
 
65
 // XReposition stuff is to prevent exceeding the dimensions of the video surface under certain conditions(weave deinterlacer, previous field has higher
 
66
 // horizontal resolution than current field, and current field's rectangle has an x offset that's too large when taking into consideration the previous field's
 
67
 // width; for simplicity, we don't check widths, but just assume that the previous field's maximum width is >= than the current field's maximum width).
 
68
 //
 
69
 const int32 XReposition = ((WeaveGood && DisplayRect.x > PrevDRect.x) ? DisplayRect.x : 0);
 
70
 
 
71
 //printf("%2d %2d, %d\n", DisplayRect.x, PrevDRect.x, XReposition);
 
72
 
 
73
 if(XReposition)
 
74
  DisplayRect.x = 0;
 
75
 
56
76
 if(surface->h && !LineWidths_In_Valid)
57
77
 {
58
 
  LineWidths[0].x = 0;
59
 
  LineWidths[0].w = 0;
 
78
  LineWidths[0] = 0;
60
79
 }
61
80
 
62
81
 for(int y = 0; y < DisplayRect.h / 2; y++)
65
84
  // set all relevant source line widths to the contents of DisplayRect(also simplifies the src_lw and related pointer calculation code
66
85
  // farther below.
67
86
  if(!LineWidths_In_Valid)
68
 
   LineWidths[(y * 2) + field + DisplayRect.y] = DisplayRect;
69
 
 
70
 
  if(StateValid && PrevHeight == DisplayRect.h && DeintType == DEINT_WEAVE)
 
87
   LineWidths[(y * 2) + field + DisplayRect.y] = DisplayRect.w;
 
88
 
 
89
  if(XReposition)
 
90
  {
 
91
    memmove(surface->pix<T>() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix,
 
92
            surface->pix<T>() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + XReposition,
 
93
            LineWidths[(y * 2) + field + DisplayRect.y] * sizeof(T));
 
94
  }
 
95
 
 
96
  if(WeaveGood)
71
97
  {
72
98
   const T* src = FieldBuffer->pix<T>() + y * FieldBuffer->pitchinpix;
73
 
   T* dest = surface->pix<T>() + ((y * 2) + (field ^ 1) + DisplayRect.y) * surface->pitchinpix;
74
 
   MDFN_Rect *dest_lw = &LineWidths[(y * 2) + (field ^ 1) + DisplayRect.y];
 
99
   T* dest = surface->pix<T>() + ((y * 2) + (field ^ 1) + DisplayRect.y) * surface->pitchinpix + DisplayRect.x;
 
100
   int32 *dest_lw = &LineWidths[(y * 2) + (field ^ 1) + DisplayRect.y];
75
101
 
76
 
   dest_lw->x = 0;
77
 
   dest_lw->w = LWBuffer[y];
 
102
   *dest_lw = LWBuffer[y];
78
103
 
79
104
   memcpy(dest, src, LWBuffer[y] * sizeof(T));
80
105
  }
81
106
  else if(DeintType == DEINT_BOB)
82
107
  {
83
 
   const T* src = surface->pix<T>() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix;
84
 
   T* dest = surface->pix<T>() + ((y * 2) + (field ^ 1) + DisplayRect.y) * surface->pitchinpix;
85
 
   const MDFN_Rect *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y];
86
 
   MDFN_Rect *dest_lw = &LineWidths[(y * 2) + (field ^ 1) + DisplayRect.y];
87
 
 
88
 
   dest_lw->x = 0;
89
 
   dest_lw->w = src_lw->w;
90
 
 
91
 
   memcpy(dest, src + src_lw->x, src_lw->w * sizeof(T));
 
108
   const T* src = surface->pix<T>() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x;
 
109
   T* dest = surface->pix<T>() + ((y * 2) + (field ^ 1) + DisplayRect.y) * surface->pitchinpix + DisplayRect.x;
 
110
   const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y];
 
111
   int32 *dest_lw = &LineWidths[(y * 2) + (field ^ 1) + DisplayRect.y];
 
112
 
 
113
   *dest_lw = *src_lw;
 
114
 
 
115
   memcpy(dest, src, *src_lw * sizeof(T));
92
116
  }
93
117
  else
94
118
  {
95
 
   const MDFN_Rect *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y];
96
 
   const T* src = surface->pix<T>() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + src_lw->x;
 
119
   const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y];
 
120
   const T* src = surface->pix<T>() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x;
97
121
   const int32 dly = ((y * 2) + (field + 1) + DisplayRect.y);
98
 
   T* dest = surface->pix<T>() + dly * surface->pitchinpix;
 
122
   T* dest = surface->pix<T>() + dly * surface->pitchinpix + DisplayRect.x;
99
123
 
100
124
   if(y == 0 && field)
101
125
   {
104
128
 
105
129
    LineWidths[dly - 2] = *src_lw;
106
130
 
107
 
    for(int x = 0; x < src_lw->w; x++)
 
131
    for(int x = 0; x < *src_lw; x++)
108
132
     dm2[x] = black;
109
133
   }
110
134
 
111
135
   if(dly < (DisplayRect.y + DisplayRect.h))
112
136
   {
113
137
    LineWidths[dly] = *src_lw;
114
 
    memcpy(dest, src, src_lw->w * sizeof(T));
 
138
    memcpy(dest, src, *src_lw * sizeof(T));
115
139
   }
116
140
  }
117
141
 
123
147
  //
124
148
  if(DeintType == DEINT_WEAVE)
125
149
  {
126
 
   const MDFN_Rect *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y];
127
 
   const T* src = surface->pix<T>() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + src_lw->x;
 
150
   const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y];
 
151
   const T* src = surface->pix<T>() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x;
128
152
   T* dest = FieldBuffer->pix<T>() + y * FieldBuffer->pitchinpix;
129
153
 
130
 
   memcpy(dest, src, src_lw->w * sizeof(uint32));
131
 
   LWBuffer[y] = src_lw->w;
 
154
   memcpy(dest, src, *src_lw * sizeof(uint32));
 
155
   LWBuffer[y] = *src_lw;
132
156
 
133
157
   StateValid = true;
134
158
  }
135
159
 }
136
 
 
137
 
 PrevHeight = DisplayRect.h;
138
160
}
139
161
 
140
 
void Deinterlacer::Process(MDFN_Surface *surface, const MDFN_Rect &DisplayRect, MDFN_Rect *LineWidths, const bool field)
 
162
void Deinterlacer::Process(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field)
141
163
{
 
164
 const MDFN_Rect DisplayRect_Original = DisplayRect;
 
165
 
142
166
 if(DeintType == DEINT_WEAVE)
143
167
 {
144
168
  if(!FieldBuffer || FieldBuffer->w < surface->w || FieldBuffer->h < (surface->h / 2))
151
175
  }
152
176
  else if(memcmp(&surface->format, &FieldBuffer->format, sizeof(MDFN_PixelFormat)))
153
177
  {
154
 
   FieldBuffer->SetFormat(surface->format, StateValid && PrevHeight == DisplayRect.h);
 
178
   FieldBuffer->SetFormat(surface->format, StateValid && PrevDRect.h == DisplayRect.h);
155
179
  }
156
180
 }
157
181
 
169
193
        InternalProcess<uint32>(surface, DisplayRect, LineWidths, field);
170
194
        break;
171
195
 }
 
196
 
 
197
 PrevDRect = DisplayRect_Original;
172
198
}
173
199
 
174
200
void Deinterlacer::ClearState(void)
175
201
{
176
202
 StateValid = false;
177
 
 PrevHeight = 0;
 
203
 
 
204
 PrevDRect.x = 0;
 
205
 PrevDRect.y = 0;
 
206
 
 
207
 PrevDRect.w = 0;
 
208
 PrevDRect.h = 0;
178
209
}