Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Side by Side Diff: cc/android_region.cc

Issue 11369103: Compare SkRegion and android::Region performance. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/android_region.h ('k') | cc/android_region_helper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "cc/android_region.h"
18
19 #include <limits>
20
21 #include "cc/android_region_helper.h"
22 #include "third_party/skia/include/core/SkRect.h"
23 #include "ui/gfx/rect.h"
24
25 // ----------------------------------------------------------------------------
26 #define VALIDATE_REGIONS (false)
27 #define VALIDATE_WITH_CORECG (false)
28 // ----------------------------------------------------------------------------
29
30 #if VALIDATE_WITH_CORECG
31 #include <core/SkRegion.h>
32 #endif
33
34 namespace android {
35 // ----------------------------------------------------------------------------
36
37 enum {
38 op_nand = region_operator<SkIRect, int>::op_nand,
39 op_and = region_operator<SkIRect, int>::op_and,
40 op_or = region_operator<SkIRect, int>::op_or,
41 op_xor = region_operator<SkIRect, int>::op_xor
42 };
43
44 // ----------------------------------------------------------------------------
45
46 Region::Region()
47 : mBounds(SkIRect::MakeWH(0,0))
48 {
49 }
50
51 Region::Region(const Region& rhs)
52 : mBounds(rhs.mBounds), mStorage(rhs.mStorage)
53 {
54 #if VALIDATE_REGIONS
55 validate(rhs, "rhs copy-ctor");
56 #endif
57 }
58
59 Region::Region(const SkIRect& rhs)
60 : mBounds(rhs)
61 {
62 }
63
64 #if 0
65 Region::Region(const void* buffer)
66 {
67 status_t err = read(buffer);
68 ALOGE_IF(err<0, "error %s reading Region from buffer", strerror(err));
69 }
70 #endif
71
72 Region::~Region()
73 {
74 }
75
76 Region& Region::operator = (const Region& rhs)
77 {
78 #if VALIDATE_REGIONS
79 validate(*this, "this->operator=");
80 validate(rhs, "rhs.operator=");
81 #endif
82 mBounds = rhs.mBounds;
83 mStorage = rhs.mStorage;
84 return *this;
85 }
86
87 Region& Region::makeBoundsSelf()
88 {
89 mStorage.clear();
90 return *this;
91 }
92
93 void Region::clear()
94 {
95 mBounds.setEmpty();
96 mStorage.clear();
97 }
98
99 void Region::set(const SkIRect& r)
100 {
101 mBounds = r;
102 mStorage.clear();
103 }
104
105 void Region::set(int w, int h)
106 {
107 mBounds = SkIRect::MakeWH(w, h);
108 mStorage.clear();
109 }
110
111 // ----------------------------------------------------------------------------
112
113 void Region::addRectUnchecked(int l, int t, int r, int b)
114 {
115 mStorage.push_back(SkIRect::MakeLTRB(l,t,r,b));
116 #if VALIDATE_REGIONS
117 validate(*this, "addRectUnchecked");
118 #endif
119 }
120
121 // ----------------------------------------------------------------------------
122
123 Region& Region::orSelf(const SkIRect& r) {
124 return operationSelf(r, op_or);
125 }
126 Region& Region::xorSelf(const SkIRect& r) {
127 return operationSelf(r, op_xor);
128 }
129 Region& Region::andSelf(const SkIRect& r) {
130 return operationSelf(r, op_and);
131 }
132 Region& Region::subtractSelf(const SkIRect& r) {
133 return operationSelf(r, op_nand);
134 }
135 Region& Region::operationSelf(const SkIRect& r, int op) {
136 Region lhs(*this);
137 boolean_operation(op, *this, lhs, r);
138 return *this;
139 }
140
141 // ----------------------------------------------------------------------------
142
143 Region& Region::orSelf(const Region& rhs) {
144 return operationSelf(rhs, op_or);
145 }
146 Region& Region::xorSelf(const Region& rhs) {
147 return operationSelf(rhs, op_xor);
148 }
149 Region& Region::andSelf(const Region& rhs) {
150 return operationSelf(rhs, op_and);
151 }
152 Region& Region::subtractSelf(const Region& rhs) {
153 return operationSelf(rhs, op_nand);
154 }
155 Region& Region::operationSelf(const Region& rhs, int op) {
156 Region lhs(*this);
157 boolean_operation(op, *this, lhs, rhs);
158 return *this;
159 }
160
161 Region& Region::translateSelf(int x, int y) {
162 if (x|y) translate(*this, x, y);
163 return *this;
164 }
165
166 // ----------------------------------------------------------------------------
167
168 const Region Region::merge(const SkIRect& rhs) const {
169 return operation(rhs, op_or);
170 }
171 const Region Region::mergeExclusive(const SkIRect& rhs) const {
172 return operation(rhs, op_xor);
173 }
174 const Region Region::intersect(const SkIRect& rhs) const {
175 return operation(rhs, op_and);
176 }
177 const Region Region::subtract(const SkIRect& rhs) const {
178 return operation(rhs, op_nand);
179 }
180 const Region Region::operation(const SkIRect& rhs, int op) const {
181 Region result;
182 boolean_operation(op, result, *this, rhs);
183 return result;
184 }
185
186 // ----------------------------------------------------------------------------
187
188 const Region Region::merge(const Region& rhs) const {
189 return operation(rhs, op_or);
190 }
191 const Region Region::mergeExclusive(const Region& rhs) const {
192 return operation(rhs, op_xor);
193 }
194 const Region Region::intersect(const Region& rhs) const {
195 return operation(rhs, op_and);
196 }
197 const Region Region::subtract(const Region& rhs) const {
198 return operation(rhs, op_nand);
199 }
200 const Region Region::operation(const Region& rhs, int op) const {
201 Region result;
202 boolean_operation(op, result, *this, rhs);
203 return result;
204 }
205
206 const Region Region::translate(int x, int y) const {
207 Region result;
208 translate(result, *this, x, y);
209 return result;
210 }
211
212 // ----------------------------------------------------------------------------
213
214 Region& Region::orSelf(const Region& rhs, int dx, int dy) {
215 return operationSelf(rhs, dx, dy, op_or);
216 }
217 Region& Region::xorSelf(const Region& rhs, int dx, int dy) {
218 return operationSelf(rhs, dx, dy, op_xor);
219 }
220 Region& Region::andSelf(const Region& rhs, int dx, int dy) {
221 return operationSelf(rhs, dx, dy, op_and);
222 }
223 Region& Region::subtractSelf(const Region& rhs, int dx, int dy) {
224 return operationSelf(rhs, dx, dy, op_nand);
225 }
226 Region& Region::operationSelf(const Region& rhs, int dx, int dy, int op) {
227 Region lhs(*this);
228 boolean_operation(op, *this, lhs, rhs, dx, dy);
229 return *this;
230 }
231
232 // ----------------------------------------------------------------------------
233
234 const Region Region::merge(const Region& rhs, int dx, int dy) const {
235 return operation(rhs, dx, dy, op_or);
236 }
237 const Region Region::mergeExclusive(const Region& rhs, int dx, int dy) const {
238 return operation(rhs, dx, dy, op_xor);
239 }
240 const Region Region::intersect(const Region& rhs, int dx, int dy) const {
241 return operation(rhs, dx, dy, op_and);
242 }
243 const Region Region::subtract(const Region& rhs, int dx, int dy) const {
244 return operation(rhs, dx, dy, op_nand);
245 }
246 const Region Region::operation(const Region& rhs, int dx, int dy, int op) const {
247 Region result;
248 boolean_operation(op, result, *this, rhs, dx, dy);
249 return result;
250 }
251
252 // ----------------------------------------------------------------------------
253
254 // This is our region rasterizer, which merges rects and spans together
255 // to obtain an optimal region.
256 class Region::rasterizer : public region_operator<SkIRect, int>::region_rasteriz er
257 {
258 SkIRect& bounds;
259 std::vector<SkIRect>& storage;
260 SkIRect* head;
261 SkIRect* tail;
262 std::vector<SkIRect> span;
263 SkIRect* cur;
264 public:
265 rasterizer(Region& reg)
266 : bounds(reg.mBounds), storage(reg.mStorage), head(), tail(), cur() {
267 bounds.fTop = bounds.fBottom = 0;
268 bounds.fLeft = INT_MAX;
269 bounds.fRight = INT_MIN;
270 storage.clear();
271 }
272
273 ~rasterizer() {
274 if (span.size()) {
275 flushSpan();
276 }
277 if (storage.size()) {
278 bounds.fTop = storage.front().fTop;
279 bounds.fBottom = storage.back().fBottom;
280 if (storage.size() == 1) {
281 storage.clear();
282 }
283 } else {
284 bounds.fLeft = 0;
285 bounds.fRight = 0;
286 }
287 }
288
289 virtual void operator()(const SkIRect& rect) {
290 //ALOGD(">>> %3d, %3d, %3d, %3d",
291 // rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
292 if (span.size()) {
293 if (cur->fTop != rect.fTop) {
294 flushSpan();
295 } else if (cur->fRight == rect.fLeft) {
296 cur->fRight = rect.fRight;
297 return;
298 }
299 }
300 span.push_back(rect);
301 cur = &span.front() + (span.size() - 1);
302 }
303 private:
304 template<typename T>
305 static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; }
306 template<typename T>
307 static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; }
308 void flushSpan() {
309 bool merge = false;
310 if (tail-head == ssize_t(span.size())) {
311 SkIRect const* p = &span.front();
312 SkIRect const* q = head;
313 if (p->fTop == q->fBottom) {
314 merge = true;
315 while (q != tail) {
316 if ((p->fLeft != q->fLeft) || (p->fRight != q->fRight)) {
317 merge = false;
318 break;
319 }
320 p++, q++;
321 }
322 }
323 }
324 if (merge) {
325 const int bottom = span[0].fBottom;
326 SkIRect* r = head;
327 while (r != tail) {
328 r->fBottom = bottom;
329 r++;
330 }
331 } else {
332 bounds.fLeft = min(span.front().fLeft, bounds.fLeft);
333 bounds.fRight = max(span.back().fRight, bounds.fRight);
334 storage.insert(storage.end(), span.begin(), span.end());
335 tail = &storage.front() + storage.size();
336 head = tail - span.size();
337 }
338 span.clear();
339 }
340 };
341
342 bool Region::validate(const Region& reg, const char* name)
343 {
344 #if !VALIDATE_REGIONS
345 return true;
346 #else
347 bool result = true;
348 const_iterator cur = reg.begin();
349 const_iterator const tail = reg.end();
350 const_iterator prev = cur++;
351 SkIRect b(*prev);
352 while (cur != tail) {
353 b.fLeft = b.fLeft < cur->fLeft ? b.fLeft : cur->fLeft;
354 b.fTop = b.fTop < cur->fTop ? b.fTop : cur->fTop;
355 b.fRight = b.fRight > cur->fRight ? b.fRight : cur->fRight;
356 b.fBottom = b.fBottom > cur->fBottom ? b.fBottom : cur->fBottom;
357 if (cur->fTop == prev->fTop) {
358 if (cur->fBottom != prev->fBottom) {
359 ALOGE("%s: invalid span %p", name, cur);
360 result = false;
361 } else if (cur->fLeft < prev->fRight) {
362 ALOGE("%s: spans overlap horizontally prev=%p, cur=%p",
363 name, prev, cur);
364 result = false;
365 }
366 } else if (cur->fTop < prev->fBottom) {
367 ALOGE("%s: spans overlap vertically prev=%p, cur=%p",
368 name, prev, cur);
369 result = false;
370 }
371 prev = cur;
372 cur++;
373 }
374 if (b != reg.getBounds()) {
375 result = false;
376 ALOGE("%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
377 b.fLeft, b.fTop, b.fRight, b.fBottom,
378 reg.getBounds().fLeft, reg.getBounds().fTop,
379 reg.getBounds().fRight, reg.getBounds().fBottom);
380 }
381 if (result == false) {
382 reg.dump(name);
383 }
384 return result;
385 #endif
386 }
387
388 void Region::boolean_operation(int op, Region& dst,
389 const Region& lhs,
390 const Region& rhs, int dx, int dy)
391 {
392 #if VALIDATE_REGIONS
393 validate(lhs, "boolean_operation (before): lhs");
394 validate(rhs, "boolean_operation (before): rhs");
395 validate(dst, "boolean_operation (before): dst");
396 #endif
397
398 size_t lhs_count;
399 SkIRect const * const lhs_rects = lhs.getArray(&lhs_count);
400
401 size_t rhs_count;
402 SkIRect const * const rhs_rects = rhs.getArray(&rhs_count);
403
404 region_operator<SkIRect, int>::region lhs_region(lhs_rects, lhs_count);
405 region_operator<SkIRect, int>::region rhs_region(rhs_rects, rhs_count, dx, d y);
406 region_operator<SkIRect, int> operation(op, lhs_region, rhs_region);
407 { // scope for rasterizer (dtor has side effects)
408 rasterizer r(dst);
409 operation(r);
410 }
411
412 #if VALIDATE_REGIONS
413 validate(lhs, "boolean_operation: lhs");
414 validate(rhs, "boolean_operation: rhs");
415 validate(dst, "boolean_operation: dst");
416 #endif
417
418 #if VALIDATE_WITH_CORECG
419 SkRegion sk_lhs;
420 SkRegion sk_rhs;
421 SkRegion sk_dst;
422
423 for (size_t i=0 ; i<lhs_count ; i++)
424 sk_lhs.op(
425 lhs_rects[i].fLeft + dx,
426 lhs_rects[i].fTop + dy,
427 lhs_rects[i].fRight + dx,
428 lhs_rects[i].fBottom + dy,
429 SkRegion::kUnion_Op);
430
431 for (size_t i=0 ; i<rhs_count ; i++)
432 sk_rhs.op(
433 rhs_rects[i].fLeft + dx,
434 rhs_rects[i].fTop + dy,
435 rhs_rects[i].fRight + dx,
436 rhs_rects[i].fBottom + dy,
437 SkRegion::kUnion_Op);
438
439 const char* name = "---";
440 SkRegion::Op sk_op;
441 switch (op) {
442 case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break;
443 case op_xor: sk_op = SkRegion::kUnion_XOR; name="XOR"; break;
444 case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break;
445 case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break;
446 }
447 sk_dst.op(sk_lhs, sk_rhs, sk_op);
448
449 if (sk_dst.isEmpty() && dst.isEmpty())
450 return;
451
452 bool same = true;
453 Region::const_iterator head = dst.begin();
454 Region::const_iterator const tail = dst.end();
455 SkRegion::Iterator it(sk_dst);
456 while (!it.done()) {
457 if (head != tail) {
458 if (
459 head->fLeft != it.rect().fLeft ||
460 head->fTop != it.rect().fTop ||
461 head->fRight != it.rect().fRight ||
462 head->fBottom != it.rect().fBottom
463 ) {
464 same = false;
465 break;
466 }
467 } else {
468 same = false;
469 break;
470 }
471 head++;
472 it.next();
473 }
474
475 if (head != tail) {
476 same = false;
477 }
478
479 if(!same) {
480 ALOGD("---\nregion boolean %s failed", name);
481 lhs.dump("lhs");
482 rhs.dump("rhs");
483 dst.dump("dst");
484 ALOGD("should be");
485 SkRegion::Iterator it(sk_dst);
486 while (!it.done()) {
487 ALOGD(" [%3d, %3d, %3d, %3d]",
488 it.rect().fLeft,
489 it.rect().fTop,
490 it.rect().fRight,
491 it.rect().fBottom);
492 it.next();
493 }
494 }
495 #endif
496 }
497
498 void Region::boolean_operation(int op, Region& dst,
499 const Region& lhs,
500 const SkIRect& rhs, int dx, int dy)
501 {
502 if (rhs.width() < 0 || rhs.height() < 0) {
503 #if 0
504 ALOGE("Region::boolean_operation(op=%d) invalid SkIRect={%d,%d,%d,%d}",
505 op, rhs.fLeft, rhs.fTop, rhs.fRight, rhs.fBottom);
506 #endif
507 return;
508 }
509
510 #if VALIDATE_WITH_CORECG || VALIDATE_REGIONS
511 boolean_operation(op, dst, lhs, Region(rhs), dx, dy);
512 #else
513 size_t lhs_count;
514 SkIRect const * const lhs_rects = lhs.getArray(&lhs_count);
515
516 region_operator<SkIRect, int>::region lhs_region(lhs_rects, lhs_count);
517 region_operator<SkIRect, int>::region rhs_region(&rhs, 1, dx, dy);
518 region_operator<SkIRect, int> operation(op, lhs_region, rhs_region);
519 { // scope for rasterizer (dtor has side effects)
520 rasterizer r(dst);
521 operation(r);
522 }
523
524 #endif
525 }
526
527 void Region::boolean_operation(int op, Region& dst,
528 const Region& lhs, const Region& rhs)
529 {
530 boolean_operation(op, dst, lhs, rhs, 0, 0);
531 }
532
533 void Region::boolean_operation(int op, Region& dst,
534 const Region& lhs, const SkIRect& rhs)
535 {
536 boolean_operation(op, dst, lhs, rhs, 0, 0);
537 }
538
539 void Region::translate(Region& reg, int dx, int dy)
540 {
541 if (!reg.isEmpty()) {
542 #if VALIDATE_REGIONS
543 validate(reg, "translate (before)");
544 #endif
545 reg.mBounds.offset(dx, dy);
546 size_t count = reg.mStorage.size();
547 SkIRect* rects = &reg.mStorage.front();
548 while (count) {
549 rects->offset(dx, dy);
550 rects++;
551 count--;
552 }
553 #if VALIDATE_REGIONS
554 validate(reg, "translate (after)");
555 #endif
556 }
557 }
558
559 void Region::translate(Region& dst, const Region& reg, int dx, int dy)
560 {
561 dst = reg;
562 translate(dst, dx, dy);
563 }
564
565 // ----------------------------------------------------------------------------
566 #if 0
567 ssize_t Region::write(void* buffer, size_t size) const
568 {
569 #if VALIDATE_REGIONS
570 validate(*this, "write(buffer)");
571 #endif
572 const size_t count = mStorage.size();
573 const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(SkIRect);
574 if (buffer != NULL) {
575 if (sizeNeeded > size) return NO_MEMORY;
576 int32_t* const p = static_cast<int32_t*>(buffer);
577 *p = count;
578 memcpy(p+1, &mBounds, sizeof(SkIRect));
579 if (count) {
580 memcpy(p+5, &mStorage.front(), count*sizeof(SkIRect));
581 }
582 }
583 return ssize_t(sizeNeeded);
584 }
585
586 ssize_t Region::read(const void* buffer)
587 {
588 int32_t const* const p = static_cast<int32_t const*>(buffer);
589 const size_t count = *p;
590 memcpy(&mBounds, p+1, sizeof(SkIRect));
591 mStorage.clear();
592 if (count) {
593 mStorage.insertAt(0, count);
594 memcpy(&mStorage.front(), p+5, count*sizeof(SkIRect));
595 }
596 #if VALIDATE_REGIONS
597 validate(*this, "read(buffer)");
598 #endif
599 return ssize_t(sizeof(int32_t) + (1+count)*sizeof(SkIRect));
600 }
601
602 ssize_t Region::writeEmpty(void* buffer, size_t size)
603 {
604 const size_t sizeNeeded = sizeof(int32_t) + sizeof(SkIRect);
605 if (sizeNeeded > size) return NO_MEMORY;
606 int32_t* const p = static_cast<int32_t*>(buffer);
607 memset(p, 0, sizeNeeded);
608 return ssize_t(sizeNeeded);
609 }
610
611 bool Region::isEmpty(void* buffer)
612 {
613 int32_t const* const p = static_cast<int32_t const*>(buffer);
614 SkIRect const* const b = reinterpret_cast<SkIRect const *>(p+1);
615 return b->isEmpty();
616 }
617 #endif
618 // ----------------------------------------------------------------------------
619
620 Region::const_iterator Region::begin() const {
621 return isRect() ? &mBounds : &mStorage.front();
622 }
623
624 Region::const_iterator Region::end() const {
625 if (isRect()) {
626 if (isEmpty()) {
627 return &mBounds;
628 } else {
629 return &mBounds + 1;
630 }
631 } else {
632 return &mStorage.front() + mStorage.size();
633 }
634 }
635
636 SkIRect const* Region::getArray(size_t* count) const {
637 const_iterator const b(begin());
638 const_iterator const e(end());
639 if (count) *count = e-b;
640 return b;
641 }
642
643 size_t Region::getRects(std::vector<SkIRect>& rectList) const
644 {
645 rectList = mStorage;
646 if (rectList.empty()) {
647 rectList.clear();
648 rectList.push_back(mBounds);
649 }
650 return rectList.size();
651 }
652
653 // ----------------------------------------------------------------------------
654 #if 0
655 void Region::dump(String8& out, const char* what, uint32_t flags) const
656 {
657 (void)flags;
658 const_iterator head = begin();
659 const_iterator const tail = end();
660
661 size_t SIZE = 256;
662 char buffer[SIZE];
663
664 snprintf(buffer, SIZE, " Region %s (this=%p, count=%d)\n",
665 what, this, tail-head);
666 out.append(buffer);
667 while (head != tail) {
668 snprintf(buffer, SIZE, " [%3d, %3d, %3d, %3d]\n",
669 head->fLeft, head->fTop, head->fRight, head->fBottom);
670 out.append(buffer);
671 head++;
672 }
673 }
674
675 void Region::dump(const char* what, uint32_t flags) const
676 {
677 (void)flags;
678 const_iterator head = begin();
679 const_iterator const tail = end();
680 ALOGD(" Region %s (this=%p, count=%d)\n", what, this, tail-head);
681 while (head != tail) {
682 ALOGD(" [%3d, %3d, %3d, %3d]\n",
683 head->fLeft, head->fTop, head->fRight, head->fBottom);
684 head++;
685 }
686 }
687 #endif
688 // ----------------------------------------------------------------------------
689
690 }; // namespace android
OLDNEW
« no previous file with comments | « cc/android_region.h ('k') | cc/android_region_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698